#ifndef __WX_PROPGRID_PROPGRID_H__
#define __WX_PROPGRID_PROPGRID_H__

#include <wx/dynarray.h>
#include <wx/hashmap.h>
#include <wx/variant.h>
#include <wx/longlong.h>
#include <wx/dcclient.h>
#include <wx/scrolwin.h>
#include <wx/tooltip.h>
#include <wx/datetime.h>
#include "wx/textctrl.h"


#if defined(SWIG) || defined(SWIG_TYPE_TABLE)
#if !defined(__WXPYTHON__) && !defined(__NOTWXPYTHON__)
#define __WXPYTHON__
#endif
#endif

#if !defined(DOXYGEN) && !defined(_WX_WINDOW_H_BASE_) && !defined(SWIG)
#define DOXYGEN
#endif

#if defined(SWIG) || defined(DOXYGEN)
#define wxDEPRECATED(A) A
#endif

#ifdef DOXYGEN
#include "pg_dox_mainpage.h"
#include "propdev.h"
#endif

#ifdef DOXYGEN
#define wxUSE_VALIDATORS        1
#define wxUSE_DATETIME          1
#define wxUSE_TOOLTIPS          1
#define wxUSE_SPINBTN           1
#define wxUSE_DATEPICKCTRL      1
#define wxPG_COMPATIBILITY_1_2_0    0
#endif

#define wxPROPGRID_MAJOR          1
#define wxPROPGRID_MINOR          4
#define wxPROPGRID_RELEASE        16

#define wxCHECK_PROPGRID_VERSION(major,minor,release) \
  (wxPROPGRID_MAJOR > (major) || \
   (wxPROPGRID_MAJOR == (major) && wxPROPGRID_MINOR > (minor)) || \
   (wxPROPGRID_MAJOR == (major) && wxPROPGRID_MINOR == (minor) && wxPROPGRID_RELEASE >= (release)))

#define wxPG_XBEFORETEXT  5
#define wxPG_XBEFOREWIDGET  1
#define wxPG_TEXTCTRLXADJUST  3
#define wxPG_ICON_WIDTH  9
#define wxPG_USE_RENDERER_NATIVE  0
#define wxPG_DOUBLE_BUFFER  1
#define wxPG_SUPPORT_TOOLTIPS  1
#define wxPG_CONTROL_MARGIN  0
#define wxCC_CUSTOM_IMAGE_MARGIN1  4
#define wxCC_CUSTOM_IMAGE_MARGIN2  5
#define wxPG_STD_CUST_IMAGE_HEIGHT(LINEHEIGHT)  (LINEHEIGHT-3)
#define wxPG_SMALL_SCREEN  0
#define wxPG_INCLUDE_ADVPROPS   1
#define wxPG_INCLUDE_MANAGER   1
#define wxPG_INCLUDE_CHECKBOX   1
#define wxPG_USE_STL   wxUSE_STL
#define wxPG_USING_WXOWNERDRAWNCOMBOBOX 1
#define wxPGComboCtrl   wxComboCtrl
#define wxPGOwnerDrawnComboBox   wxOwnerDrawnComboBox
#define wxPGCC_DCLICK_CYCLES   wxCC_SPECIAL_DCLICK
#define wxPGCC_PAINTING_CONTROL   wxODCB_PAINTING_CONTROL
#define wxPGCC_PAINTING_SELECTED   wxODCB_PAINTING_SELECTED
#define wxPGCC_PROCESS_ENTER   wxTE_PROCESS_ENTER
#define wxPGCC_ALT_KEYS   0
#define wxPGRectContains Contains
#define wxPGIndex unsigned int
#define wxGDI_IS_OK(OBJ) ((OBJ).IsOk())
#define wxPG_COMPATIBILITY_1_2_0   0
#define wxPG_VALUETYPE_IS_STRING   0
#define wxUniChar   wxChar
#define wxPGGetIterChar(str, i)  *i
#define wxPG_CONST_WXCHAR_PTR   const wxChar*
#define wxPG_CONST_WXCHAR_DEFVAL   ((const wxChar*)NULL)
#define wxPG_TO_WXCHAR_PTR(A)   A
#define SetPropertyValueLong   SetPropertyValue
#define SetPropertyValueDouble   SetPropertyValue
#define SetPropertyValueBool   SetPropertyValue
#define SetPropertyValueString   SetPropertyValue
#define SetPropertyValueWxObjectPtr   SetPropertyValue
#define SetPropertyValuePoint   SetPropertyValue
#define SetPropertyValueSize   SetPropertyValue
#define SetPropertyValueArrint2   SetPropertyValue
#define SetPropertyValueArrstr2   SetPropertyValue
#define SetPropertyValueDatetime   SetPropertyValue
#define SetPropertyValueLongLong   SetPropertyValue
#define SetPropertyValueULongLong   SetPropertyValue
#define WX_PG_NOT_PURE_IN_WXPYTHON   =0
#define wxPG_NO_DECL

#define WXDLLIMPEXP_PG __attribute__ ((visibility ("default")))

class WXDLLIMPEXP_PG wxPGEditor;
class WXDLLIMPEXP_PG wxPGProperty;
class WXDLLIMPEXP_PG wxPropertyCategory;
class WXDLLIMPEXP_PG wxPGChoices;
class WXDLLIMPEXP_PG wxPropertyGridState;
class WXDLLIMPEXP_PG wxPGCell;
class WXDLLIMPEXP_PG wxPGChoiceEntry;
class WXDLLIMPEXP_PG wxPropertyGridInterface;
class WXDLLIMPEXP_PG wxPropertyGrid;
class WXDLLIMPEXP_PG wxPropertyGridEvent;
class WXDLLIMPEXP_PG wxPropertyGridManager;
class WXDLLIMPEXP_PG wxOwnerDrawnComboBox;
class WXDLLIMPEXP_PG wxPGCustomComboControl;
class WXDLLIMPEXP_PG wxPGEditorDialogAdapter;
class wxStatusBar;

extern WXDLLIMPEXP_PG const wxChar *wxPropertyGridNameStr;
struct WXDLLIMPEXP_PG wxPGValidationInfo;

struct wxPGPaintData {
  const wxPropertyGrid* m_parent;
  int m_choiceItem;
  int m_drawnWidth;
  int m_drawnHeight;
};

class WXDLLIMPEXP_PG wxPGCellRenderer {
  public:

    wxPGCellRenderer( unsigned int refCount = 1 )
      : m_refCount( refCount ) { }
    virtual ~wxPGCellRenderer() { }
    enum {
      Selected = 0x00010000,
      Control = 0x00020000
    };
    virtual void Render( wxDC& dc, const wxRect& rect, const wxPropertyGrid* propertyGrid,
                         wxPGProperty* property, int column, int item, int flags ) const = 0;
    virtual wxSize GetImageSize( const wxPGProperty* property, int column, int item ) const;
    virtual void DrawCaptionSelectionRect( wxDC& dc, int x, int y, int w, int h ) const;
    void DrawText( wxDC& dc, const wxRect& rect, int imageWidth, const wxString& text ) const;
    void DrawEditorValue( wxDC& dc, const wxRect& rect, int xOffset, const wxString& text, wxPGProperty* property,
                          const wxPGEditor* editor ) const;
    int PreDrawCell( wxDC& dc, const wxRect& rect, const wxPGCell& cell, int flags ) const;
    void PostDrawCell( wxDC& dc, const wxPropertyGrid* propGrid, const wxPGCell& cell, int flags ) const;
    void IncRef() {
      m_refCount++;
    }
    void DecRef() {
      m_refCount--;
      if( !m_refCount ) {
        delete this;
      }
    }
  protected:
  private:
    unsigned int m_refCount;
};

class WXDLLIMPEXP_PG wxPGDefaultRenderer : public wxPGCellRenderer {
  public:
    virtual void Render( wxDC& dc, const wxRect& rect, const wxPropertyGrid* propertyGrid,
                         wxPGProperty* property, int column, int item, int flags ) const;

    virtual wxSize GetImageSize( const wxPGProperty* property, int column, int item ) const;

  protected:
};

class WXDLLIMPEXP_PG wxPGCell {
  public:
    wxPGCell();
    wxPGCell( const wxString& text, const wxBitmap& bitmap = wxNullBitmap, const wxColour& fgCol = wxNullColour,
              const wxColour& bgCol = wxNullColour );

    virtual ~wxPGCell() { }
    void Assign( const wxPGCell& cell );
    bool HasText() const;
    void SetText( const wxString& text ) { m_text = text; }
    void SetBitmap( const wxBitmap& bitmap ) { m_bitmap = bitmap; }
    void SetFgCol( const wxColour& col ) { m_fgCol = col; }
    void SetBgCol( const wxColour& col ) { m_bgCol = col; }
    void SetFont( const wxFont& font ) { m_font = font; }
    const wxString& GetText() const { return m_text; }
    const wxBitmap& GetBitmap() const { return m_bitmap; }
    const wxColour& GetFgCol() const { return m_fgCol; }
    const wxColour& GetBgCol() const { return m_bgCol; }
    const wxFont& GetFont() const { return m_font; }
  protected:
    wxString m_text;
    wxBitmap m_bitmap;
    wxColour m_fgCol;
    wxColour m_bgCol;
    wxFont m_font;
};

#define wxPG_EMPTY_ARRAYINT     wxArrayInt()
#define wxPG_EMPTY_ARRAYSTRING  wxArrayString()
extern wxString WXDLLIMPEXP_PG wxString_wxPG_LABEL;
#define wxPG_LABEL              wxString_wxPG_LABEL
#define wxPG_NULL_BITMAP        wxNullBitmap
#define wxPG_COLOUR_BLACK       (*wxBLACK)
#define wxPG_INVALID_VALUE      INT_MAX
#define wxPG_COLOUR(R,G,B) ((wxUint32)(R+(G<<8)+(B<<16)))
#define wxPG_DEFAULT_IMAGE_SIZE             wxSize(-1, -1)

typedef bool ( *wxPropertyGridCallback )( wxPropertyGrid* propGrid, wxPGProperty* property, wxWindow* ctrl, int data );
typedef void ( *wxPGPaintCallback )( wxPGProperty* property, wxDC& dc, const wxRect& rect, wxPGPaintData& paintdata );
typedef int ( *wxPGSortCallback )( wxPropertyGrid* propGrid, wxPGProperty* p1, wxPGProperty* p2 );

#define WX_PG_CLASSINFO(NAME) (&NAME::ms_classInfo)


typedef wxString wxPGCachedString;

enum wxPG_WINDOW_STYLES {
  wxPG_AUTO_SORT = 0x00000010,
  wxPG_HIDE_CATEGORIES = 0x00000020,
  wxPG_ALPHABETIC_MODE = ( wxPG_HIDE_CATEGORIES | wxPG_AUTO_SORT ),
  wxPG_BOLD_MODIFIED = 0x00000040,
  wxPG_SPLITTER_AUTO_CENTER = 0x00000080,
  wxPG_TOOLTIPS = 0x00000100,
  wxPG_HIDE_MARGIN = 0x00000200,
  wxPG_STATIC_SPLITTER = 0x00000400,
  wxPG_STATIC_LAYOUT = ( wxPG_HIDE_MARGIN | wxPG_STATIC_SPLITTER ),
  wxPG_LIMITED_EDITING = 0x00000800,
  wxPG_TOOLBAR = 0x00001000,
  wxPG_DESCRIPTION = 0x00002000,
  wxPG_THEME_BORDER = 0x00004000,
  wxPG_NO_INTERNAL_BORDER = 0x00008000

};

enum wxPG_EX_WINDOW_STYLES {
  wxPG_EX_INIT_NOCAT = 0x00001000,
  wxPG_EX_NO_FLAT_TOOLBAR = 0x00002000,
  wxPG_EX_MODE_BUTTONS = 0x00008000,
  wxPG_EX_HELP_AS_TOOLTIPS = 0x00010000,
  wxPG_EX_NATIVE_DOUBLE_BUFFERING = 0x00080000,
  wxPG_EX_AUTO_UNSPECIFIED_VALUES = 0x00200000,
  wxPG_EX_WRITEONLY_BUILTIN_ATTRIBUTES = 0x00400000,
  wxPG_EX_LEGACY_VALIDATORS = 0x00800000,
  wxPG_EX_HIDE_PAGE_BUTTONS = 0x01000000,
  wxPG_EX_UNFOCUS_ON_ENTER = 0x02000000,
  wxPG_EX_MULTIPLE_SELECTION = 0x04000000,
  wxPG_EX_DISABLE_TLP_TRACKING = 0x08000000,
  wxPG_EX_NO_TOOLBAR_DIVIDER = 0x10000000,
  wxPG_EX_TOOLBAR_SEPARATOR = 0x20000000

};

#define wxPG_EX_ENABLE_TLP_TRACKING     0x00000000
#define wxPG_DEFAULT_STYLE          (0)
#define wxPGMAN_DEFAULT_STYLE     (0)

enum wxPG_GETPROPERTYVALUES_FLAGS {
  wxPG_KEEP_STRUCTURE = 0x00000010,
  wxPG_RECURSE = 0x00000020,
  wxPG_INC_ATTRIBUTES = 0x00000040,
  wxPG_RECURSE_STARTS = 0x00000080,
  wxPG_FORCE = 0x00000100

};

#define wxPG_DONT_RECURSE         0x00000000

enum wxPG_MISC_ARG_FLAGS {
  wxPG_FULL_VALUE = 0x00000001,
  wxPG_REPORT_ERROR = 0x00000002,
  wxPG_PROPERTY_SPECIFIC = 0x00000004,
  wxPG_EDITABLE_VALUE = 0x00000008,
  wxPG_COMPOSITE_FRAGMENT = 0x00000010,
  wxPG_UNEDITABLE_COMPOSITE_FRAGMENT = 0x00000020,
  wxPG_PROGRAMMATIC_VALUE = 0x00000040
};

enum wxPG_SETVALUE_FLAGS {
  wxPG_SETVAL_REFRESH_EDITOR = 0x0001,
  wxPG_SETVAL_AGGREGATED = 0x0002,
  wxPG_SETVAL_FROM_PARENT = 0x0004,
  wxPG_SETVAL_BY_USER = 0x0008
};

#define wxNullProperty  ((wxPGProperty*)NULL)
typedef wxPGProperty* wxPGId;

class WXDLLIMPEXP_PG wxPGPropArgCls {
  public:
    wxPGPropArgCls() { }
    wxPGPropArgCls( const wxPGProperty* property ) {
      m_ptr.property = ( wxPGProperty* ) property;
      m_isName = false;
    }
    wxPGPropArgCls( const wxString& str ) {
      m_ptr.name = &str;
      m_isName = 1;
    }
    wxPGPropArgCls( const wxPGPropArgCls& id ) {
      m_ptr = id.m_ptr;
      m_isName = id.m_isName;
    }
    wxPGProperty* GetPtr() const { wxCHECK( !m_isName, NULL ); return m_ptr.property; }
    wxPGPropArgCls( const wxChar* str ) {
      m_ptr.rawname = str;
      m_isName = 2;
    }
    wxPGPropArgCls( int ) {
      m_ptr.property = ( wxPGProperty* ) NULL;
      m_isName = false;
    }
    wxPGProperty* GetPtr( wxPropertyGridInterface* methods ) const;
    wxPGProperty* GetPtr( const wxPropertyGridInterface* methods ) const {
      return GetPtr( ( wxPropertyGridInterface* )methods );
    }
    wxPGProperty* GetPtr0() const { return m_ptr.property; }
    unsigned char HasName() const { return m_isName; }
    const wxString& GetName() const { return *m_ptr.name; }
  private:
    union {
      wxPGProperty* property;
      const wxChar* rawname;
      const wxString* name;
    } m_ptr;
    unsigned char m_isName;
};

typedef const wxPGPropArgCls& wxPGPropArg;

WXDLLIMPEXP_PG void wxPGTypeOperationFailed( const wxPGProperty* p, const wxChar* typestr, const wxChar* op );
WXDLLIMPEXP_PG void wxPGGetFailed( const wxPGProperty* p, const wxChar* typestr );

enum wxPGPropertyFlags {
  wxPG_PROP_MODIFIED = 0x0001,
  wxPG_PROP_DISABLED = 0x0002,
  wxPG_PROP_HIDDEN = 0x0004,
  wxPG_PROP_CUSTOMIMAGE = 0x0008,
  wxPG_PROP_NOEDITOR                  = 0x0010,
  wxPG_PROP_COLLAPSED                 = 0x0020,
  wxPG_PROP_INVALID_VALUE             = 0x0040,
  wxPG_PROP_WAS_MODIFIED              = 0x0200,
  wxPG_PROP_AGGREGATE                 = 0x0400,
  wxPG_PROP_CHILDREN_ARE_COPIES       = 0x0800,
  wxPG_PROP_PROPERTY                  = 0x1000,
  wxPG_PROP_CATEGORY                  = 0x2000,
  wxPG_PROP_MISC_PARENT               = 0x4000,
  wxPG_PROP_READONLY                  = 0x8000,
  wxPG_PROP_COMPOSED_VALUE            = 0x00010000,
  wxPG_PROP_USES_COMMON_VALUE         = 0x00020000,
  wxPG_PROP_AUTO_UNSPECIFIED          = 0x00040000,
  wxPG_PROP_CLASS_SPECIFIC_1          = 0x00080000,
  wxPG_PROP_CLASS_SPECIFIC_2          = 0x00100000,
  wxPG_PROP_BEING_DELETED             = 0x00200000

};

#define wxPG_PROP_MAX               wxPG_PROP_AUTO_UNSPECIFIED
#define wxPG_PROP_PARENTAL_FLAGS        (wxPG_PROP_AGGREGATE|wxPG_PROP_CATEGORY|wxPG_PROP_MISC_PARENT)
#define wxPG_INHERITED_PROPFLAGS        (wxPG_PROP_HIDDEN|wxPG_PROP_NOEDITOR)
#define wxPG_STRING_STORED_FLAGS        (wxPG_PROP_DISABLED|wxPG_PROP_HIDDEN|wxPG_PROP_NOEDITOR|wxPG_PROP_COLLAPSED)
#define wxPG_ATTR_MIN   _T("Min")
#define wxPG_ATTR_MAX   _T("Max")
#define wxPG_ATTR_UNITS   _T("Units")
#define wxPG_ATTR_INLINE_HELP   _T("InlineHelp")
#define wxPG_BOOL_USE_CHECKBOX   _T("UseCheckbox")
#define wxPG_BOOL_USE_DOUBLE_CLICK_CYCLING   _T("UseDClickCycling")
#define wxPG_FLOAT_PRECISION   _T("Precision")
#define wxPG_STRING_PASSWORD   _T("Password")
#define wxPG_UINT_BASE   _T("Base")
#define wxPG_UINT_PREFIX   _T("Prefix")
#define wxPG_FILE_WILDCARD   _T("Wildcard")
#define wxPG_FILE_SHOW_FULL_PATH   _T("ShowFullPath")
#define wxPG_FILE_SHOW_RELATIVE_PATH   _T("ShowRelativePath")
#define wxPG_FILE_INITIAL_PATH   _T("InitialPath")
#define wxPG_FILE_DIALOG_TITLE   _T("DialogTitle")
#define wxPG_DIR_DIALOG_MESSAGE   _T("DialogMessage")
#define wxPG_DATE_FORMAT   _T("DateFormat")
#define wxPG_DATE_PICKER_STYLE   _T("PickerStyle")
#define wxPG_ATTR_SPINCTRL_STEP   _T("Step")
#define wxPG_ATTR_SPINCTRL_WRAP   _T("Wrap")
#define wxPG_ATTR_SPINCTRL_MOTIONSPIN   _T("MotionSpin")
#define wxPG_ATTR_MULTICHOICE_USERSTRINGMODE   _T("UserStringMode")
#define wxPG_CUSTOM_PAINT_CALLBACK   _T("PaintCallback")
#define wxPG_CUSTOM_PRIVATE_CHILDREN   _T("PrivateChildren")
#define wxPG_COLOUR_ALLOW_CUSTOM   _T("AllowCustom")
#undef wxPG_ATTR_DEFAULT_VALUE
#define wxPG_ATTR_DEFAULT_VALUE   wxPGGlobalVars->m_strDefaultValue
#undef wxPG_ATTR_MIN
#define wxPG_ATTR_MIN   wxPGGlobalVars->m_strMin
#undef wxPG_ATTR_MAX
#define wxPG_ATTR_MAX   wxPGGlobalVars->m_strMax
#undef wxPG_ATTR_UNITS
#define wxPG_ATTR_UNITS   wxPGGlobalVars->m_strUnits
#undef wxPG_ATTR_INLINE_HELP
#define wxPG_ATTR_INLINE_HELP   wxPGGlobalVars->m_strInlineHelp
#define wxPG_BASE_OCT   (long)8
#define wxPG_BASE_DEC   (long)10
#define wxPG_BASE_HEX   (long)16
#define wxPG_BASE_HEXL   (long)32
#define wxPG_PREFIX_NONE   (long)0
#define wxPG_PREFIX_0x   (long)1
#define wxPG_PREFIX_DOLLAR_SIGN   (long)2
#define wxPG_EDITOR(T)   wxPGEditor_##T
#define WX_PG_DECLARE_EDITOR_WITH_DECL(EDITOR,DECL) \
  extern DECL wxPGEditor* wxPGEditor_##EDITOR; \
  extern DECL wxPGEditor* wxPGConstruct##EDITOR##EditorClass();

#define WX_PG_DECLARE_EDITOR(EDITOR) \
  extern wxPGEditor* wxPGEditor_##EDITOR; \
  extern wxPGEditor* wxPGConstruct##EDITOR##EditorClass();


WX_PG_DECLARE_EDITOR_WITH_DECL( TextCtrl, WXDLLIMPEXP_PG )
WX_PG_DECLARE_EDITOR_WITH_DECL( Choice, WXDLLIMPEXP_PG )
WX_PG_DECLARE_EDITOR_WITH_DECL( ComboBox, WXDLLIMPEXP_PG )
WX_PG_DECLARE_EDITOR_WITH_DECL( TextCtrlAndButton, WXDLLIMPEXP_PG )
WX_PG_DECLARE_EDITOR_WITH_DECL( CheckBox, WXDLLIMPEXP_PG )
WX_PG_DECLARE_EDITOR_WITH_DECL( ChoiceAndButton, WXDLLIMPEXP_PG )

#define wxVARIANT_REFCOUNTED 1

#if !defined(SWIG)
//#error mmmmmmmmmmmmmmmmmmmmmmmmmm

class WXDLLIMPEXP_PG wxPGVariantData : public wxVariantData {
    DECLARE_ABSTRACT_CLASS( wxPGVariantData )
  public:
    virtual void* GetValuePtr() = 0;
    virtual wxVariant GetDefaultValue() const = 0;
  protected:
};

#define WX_PG_DECLARE_DYNAMIC_CLASS_VARIANTDATA DECLARE_DYNAMIC_CLASS
#define WX_PG_IMPLEMENT_DYNAMIC_CLASS_VARIANTDATA IMPLEMENT_DYNAMIC_CLASS
typedef wxList wxVariantList;
typedef wxClassInfo* wxPGVariantDataClassInfo;
#define wxPGVariantDataGetClassInfo(A) (A->GetClassInfo())
#define wxPG_VARIANT_EQ(A, B) ( ((A).GetData() && (B).GetData() && (A).   \
                                 GetData()->GetClassInfo() == (B).GetData()->GetClassInfo() && (A == B)) || (!(A).GetData() && !(B).GetData()) )

#define wxDynamicCastVariantData wxDynamicCast

inline void wxPGDoesNothing() {}

#define _WX_PG_IMPLEMENT_VARIANT_DATA_CLASS(CLASSNAME, DATATYPE, AS_ARG, AS_ARG_CONST, CTOR_CODE, DEFAULT_VALUE, SET_CODE) \
  WX_PG_DECLARE_DYNAMIC_CLASS_VARIANTDATA(CLASSNAME) \
  protected: \
  DATATYPE m_value; \
  public: \
  CLASSNAME() { CTOR_CODE; } \
  CLASSNAME(AS_ARG_CONST value) { CTOR_CODE; SET_CODE; m_value = value; } \
  DATATYPE GetValue() const { return m_value; } \
  AS_ARG_CONST GetValueRef() const { return m_value; } \
  AS_ARG GetValueRef() { return m_value; } \
  void SetValue(AS_ARG_CONST value) { SET_CODE; m_value = value; } \
  virtual wxString GetType() const { return _T(#DATATYPE); } \
  virtual wxVariantData* Clone() { return new CLASSNAME; } \
  virtual bool Read(wxString &) { return false; } \
  virtual bool Write(wxString &) const { return true; } \
  virtual wxVariant GetDefaultValue() const { return DEFAULT_VALUE; }


#define _WX_PG_IMPLEMENT_VARIANT_DATA_SHALLOW_EQ(CLASSNAME, DATATYPE) \
  virtual bool Eq(wxVariantData& other) const \
  { return (this == (const wxVariantData*) &other); }

#define _WX_PG_IMPLEMENT_VARIANT_DATA_PROPER_EQ(CLASSNAME, DATATYPE) \
  virtual bool Eq(wxVariantData& other) const \
  { \
    if ( other.GetType() != _T(#DATATYPE) ) \
      return false; \
    CLASSNAME* pOther = wxStaticCast(&other, CLASSNAME); \
    return (m_value == pOther->GetValueRef()); \
  }

template<class T>
wxVariant WXVARIANT( const T& value ) {
  return wxVariant( ( void* )&value );
}

template<> inline wxVariant WXVARIANT( const int& value ) { return wxVariant( ( long )value ); }
template<> inline wxVariant WXVARIANT( const long& value ) { return wxVariant( value ); }
template<> inline wxVariant WXVARIANT( const bool& value ) { return wxVariant( value ); }
template<> inline wxVariant WXVARIANT( const double& value ) { return wxVariant( value ); }
template<> inline wxVariant WXVARIANT( const wxArrayString& value ) { return wxVariant( value ); }
template<> inline wxVariant WXVARIANT( const wxString& value ) { return wxVariant( value ); }
template<> inline wxVariant WXVARIANT( const wxDateTime& value ) { return wxVariant( value ); }

#define _WX_PG_VARIANT_DATA_CLASSINFO_CONTAINER_DECL(CLASSNAME) \
  extern wxPGVariantDataClassInfo CLASSNAME##_ClassInfo
#define _WX_PG_VARIANT_DATA_CLASSINFO_CONTAINER(CLASSNAME) \
  wxPGVariantDataClassInfo CLASSNAME##_ClassInfo = &CLASSNAME::ms_classInfo;

#define _WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE, AS_ARG, AS_CONST_ARG, NULLVAL, BASECLASS) \
  _WX_PG_VARIANT_DATA_CLASSINFO_CONTAINER(CLASSNAME) \
  WX_PG_IMPLEMENT_DYNAMIC_CLASS_VARIANTDATA(CLASSNAME, BASECLASS) \
  AS_ARG operator <<( AS_ARG value, const wxVariant &variant ) \
  { \
    CLASSNAME *data = wxDynamicCastVariantData( variant.GetData(), CLASSNAME ); \
    wxASSERT( data ); \
    value = data->GetValue(); \
    return value; \
  } \
  wxVariant& operator <<( wxVariant &variant, AS_CONST_ARG value ) \
  { \
    CLASSNAME *data = new CLASSNAME( value ); \
    variant.SetData( data ); \
    return variant; \
  } \
  AS_ARG DATATYPE##FromVariant( const wxVariant& v ) \
  { \
    CLASSNAME *data = wxDynamicCastVariantData( v.GetData(), CLASSNAME ); \
    if ( !data ) \
      return NULLVAL; \
    return data->GetValueRef(); \
  } \
  wxVariant DATATYPE##ToVariant( AS_CONST_ARG value ) \
  { \
    wxVariant variant( new CLASSNAME( value ) ); \
    return variant; \
  }

#define WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE) \
  class CLASSNAME : public wxPGVariantData \
  { \
      _WX_PG_IMPLEMENT_VARIANT_DATA_CLASS(CLASSNAME, DATATYPE, DATATYPE&, \
                                          const DATATYPE&, wxPGDoesNothing(), \
                                          wxVariant(new CLASSNAME(DATATYPE())), wxPGDoesNothing()) \
      _WX_PG_IMPLEMENT_VARIANT_DATA_SHALLOW_EQ(CLASSNAME, DATATYPE) \
    public: \
      virtual void* GetValuePtr() { return (void*)&m_value; } \
  }; \
  _WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE, DATATYPE&, const DATATYPE&, (DATATYPE&)*((DATATYPE*)NULL), wxPGVariantData)

#define WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA(CLASSNAME, DATATYPE) \
  class CLASSNAME : public wxPGVariantData \
  { \
      _WX_PG_IMPLEMENT_VARIANT_DATA_CLASS(CLASSNAME, DATATYPE, DATATYPE&, \
                                          const DATATYPE&, wxPGDoesNothing(), \
                                          wxVariant(new CLASSNAME(DATATYPE())), wxPGDoesNothing()) \
      _WX_PG_IMPLEMENT_VARIANT_DATA_SHALLOW_EQ(CLASSNAME, DATATYPE) \
    public: \
      virtual void* GetValuePtr() { return (void*)&m_value; } \
      virtual wxClassInfo* GetValueClassInfo() { return m_value.GetClassInfo(); } \
  }; \
  _WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE, DATATYPE&, const DATATYPE&, (DATATYPE&)*((DATATYPE*)NULL), wxPGVariantData)


#define WX_PG_IMPLEMENT_WXOBJECT_VARIANT_DATA_WITH_PROPER_EQ(CLASSNAME, DATATYPE) \
  class CLASSNAME : public wxPGVariantData \
  { \
      _WX_PG_IMPLEMENT_VARIANT_DATA_CLASS(CLASSNAME, DATATYPE, DATATYPE&, \
                                          const DATATYPE&, wxPGDoesNothing(), \
                                          wxVariant(new CLASSNAME(DATATYPE())), wxPGDoesNothing()) \
      _WX_PG_IMPLEMENT_VARIANT_DATA_PROPER_EQ(CLASSNAME, DATATYPE) \
    public: \
      virtual void* GetValuePtr() { return (void*)&m_value; } \
      virtual wxClassInfo* GetValueClassInfo() { return m_value.GetClassInfo(); } \
  }; \
  _WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE, DATATYPE&, const DATATYPE&, (DATATYPE&)*((DATATYPE*)NULL), wxPGVariantData)

#define WX_PG_IMPLEMENT_VARIANT_DATA_WITH_EQ(CLASSNAME, DATATYPE) \
  class CLASSNAME : public wxPGVariantData \
  { \
      _WX_PG_IMPLEMENT_VARIANT_DATA_CLASS(CLASSNAME, DATATYPE, DATATYPE&, \
                                          const DATATYPE&, wxPGDoesNothing(), \
                                          wxVariant(new CLASSNAME(DATATYPE())), wxPGDoesNothing()) \
      _WX_PG_IMPLEMENT_VARIANT_DATA_PROPER_EQ(CLASSNAME, DATATYPE) \
    public: \
      virtual void* GetValuePtr() { return (void*)&m_value; } \
  }; \
  _WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE, DATATYPE&, const DATATYPE&, (DATATYPE&)*((DATATYPE*)NULL), wxPGVariantData)


#define WX_PG_DECLARE_VARIANT_DATA(CLASSNAME, DATATYPE, DECL) \
  DECL DATATYPE& operator <<( DATATYPE& value, const wxVariant &variant ); \
  DECL wxVariant& operator <<( wxVariant &variant, const DATATYPE& value ); \
  DECL DATATYPE& DATATYPE##FromVariant( const wxVariant& variant ); \
  DECL wxVariant DATATYPE##ToVariant( const DATATYPE& value ); \
  template<> inline wxVariant WXVARIANT( const DATATYPE& value ) { return DATATYPE##ToVariant(value); } \
  DECL _WX_PG_VARIANT_DATA_CLASSINFO_CONTAINER_DECL(CLASSNAME);

#define WX_PG_DECLARE_WXOBJECT_VARIANT_DATA WX_PG_DECLARE_VARIANT_DATA

#define WX_PG_DECLARE_PTR_VARIANT_DATA(CLASSNAME, DATATYPE, DECL) \
  DECL DATATYPE* operator <<( DATATYPE* value, const wxVariant &variant ); \
  DECL wxVariant& operator <<( wxVariant &variant, DATATYPE* value ); \
  DECL DATATYPE* DATATYPE##FromVariant( const wxVariant& variant ); \
  DECL wxVariant DATATYPE##ToVariant( DATATYPE* value ); \
  DECL _WX_PG_VARIANT_DATA_CLASSINFO_CONTAINER_DECL(CLASSNAME);


#define WX_PG_IMPLEMENT_PTR_VARIANT_DATA(CLASSNAME, DATATYPE, DEFAULT) \
  class CLASSNAME : public wxPGVariantData{ \
      _WX_PG_IMPLEMENT_VARIANT_DATA_CLASS(CLASSNAME, DATATYPE*, DATATYPE*,DATATYPE*, m_value = NULL, \
                                          DEFAULT, if (m_value) Py_DECREF(m_value); if (!value) value = Py_None; Py_INCREF(value) ) \
          _WX_PG_IMPLEMENT_VARIANT_DATA_SHALLOW_EQ(CLASSNAME, DATATYPE) \
          ~CLASSNAME() { if (m_value) Py_DECREF(m_value); } \
    public: \
      virtual void* GetValuePtr() { return (void*)m_value; } \
  }; \
  _WX_PG_IMPLEMENT_VARIANT_DATA(CLASSNAME, DATATYPE, DATATYPE*, DATATYPE*, NULL, wxPGVariantData)


WX_PG_DECLARE_VARIANT_DATA( wxPGVariantDataPoint, wxPoint, WXDLLIMPEXP_PG )
WX_PG_DECLARE_VARIANT_DATA( wxPGVariantDataSize, wxSize, WXDLLIMPEXP_PG )
WX_PG_DECLARE_VARIANT_DATA( wxPGVariantDataArrayInt, wxArrayInt, WXDLLIMPEXP_PG )
WX_PG_DECLARE_VARIANT_DATA( wxPGVariantDataLongLong, wxLongLong, WXDLLIMPEXP_PG )
WX_PG_DECLARE_VARIANT_DATA( wxPGVariantDataULongLong, wxULongLong, WXDLLIMPEXP_PG )

WX_PG_DECLARE_WXOBJECT_VARIANT_DATA( wxPGVariantDataFont, wxFont, WXDLLIMPEXP_PG )

template<> inline wxVariant WXVARIANT( const wxColour& value ) {
  wxVariant variant;
  variant << value;
  return variant;
}

#endif

#define WX_PG_VARIANT_GETVALUEREF(P, T)   (*((T*)((wxPGVariantData*)(P.GetData()))->GetValuePtr()))

WXDLLIMPEXP_PG long wxPGVariantToInt( const wxVariant& variant, long defVal = 1 );
WXDLLIMPEXP_PG bool wxPGVariantToLongLong( const wxVariant& variant, wxLongLong_t* pResult );
WXDLLIMPEXP_PG bool wxPGVariantToULongLong( const wxVariant& variant, wxULongLong_t* pResult );
WXDLLIMPEXP_PG bool wxPGVariantToDouble( const wxVariant& variant, double* pResult );
WXDLLIMPEXP_PG bool wxPGVariantToWxObjectPtr( const wxVariant& value, wxObject** result );
WXDLLIMPEXP_PG void wxPGInitResourceModule();

WX_DEFINE_TYPEARRAY_WITH_DECL_PTR( wxPGProperty*, wxArrayPGProperty, wxBaseArrayPtrVoid );
WX_DECLARE_STRING_HASH_MAP_WITH_DECL( void*, wxPGHashMapS2P );



#define WX_PG_DECLARE_DOGETEDITORCLASS  virtual const wxPGEditor* DoGetEditorClass() const;
#define WX_PG_DECLARE_PROPERTY_CLASS(CLASSNAME) \
  public: \
  DECLARE_DYNAMIC_CLASS(CLASSNAME) \
  WX_PG_DECLARE_DOGETEDITORCLASS \
  private:


#define WX_PG_IMPLEMENT_PROPERTY_CLASS_PLAIN(PROPNAME,T,EDITOR) \
  const wxPGEditor* PROPNAME::DoGetEditorClass() const \
  { \
    return wxPGEditor_##EDITOR; \
  }


#define wxPG_SUBID1                     2
#define wxPG_SUBID2                     3
#define wxPG_SUBID_TEMP1                4

struct wxPGChoiceInfo {
  wxPGChoices*    m_choices;
};

class WXDLLIMPEXP_PG wxPGAttributeStorage {
  public:
    wxPGAttributeStorage();
    ~wxPGAttributeStorage();

    void Set( const wxString& name, const wxVariant& value );
    unsigned int GetCount() const {
      return ( unsigned int ) m_map.size();
    }
    wxVariant FindValue( const wxString& name ) const {
      wxPGHashMapS2P::const_iterator it = m_map.find( name );
      if( it != m_map.end() ) {
        wxVariantData* data = ( wxVariantData* ) it->second;
        data->IncRef();
        return wxVariant( data, it->first );
      }
      return wxVariant();
    }

    typedef wxPGHashMapS2P::const_iterator const_iterator;
    const_iterator StartIteration() const {
      return m_map.begin();
    }
    bool GetNext( const_iterator& it, wxVariant& variant ) const {
      if( it == m_map.end() ) {
        return false;
      }
      wxVariantData* data = ( wxVariantData* ) it->second;
      data->IncRef();
      variant.SetData( data );
      variant.SetName( it->first );
      it++;
      return true;
    }

  protected:
    wxPGHashMapS2P  m_map;
};

class WXDLLIMPEXP_PG wxPGProperty : public wxObject {
    friend class wxPropertyGrid;
    friend class wxPropertyGridInterface;
    friend class wxPropertyGridState;
    friend class wxPropertyGridPopulator;
    friend class wxStringProperty;
    DECLARE_ABSTRACT_CLASS( wxPGProperty )
  public:
    typedef wxUint32 FlagType;
    typedef void* ClientDataType;
    wxPGProperty();
    wxPGProperty( const wxString& label, const wxString& name );
    virtual ~wxPGProperty();
    virtual void OnSetValue();
    virtual wxVariant DoGetValue() const { return m_value; }
  private:
    virtual bool ValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const;
    virtual bool StringToValue( wxVariant& variant, const wxString& text, int argFlags = 0 ) const;
    virtual bool IntToValue( wxVariant& value, int number, int argFlags = 0 ) const;
  public:
    virtual wxString GetValueAsString( int argFlags = 0 ) const;
    bool SetValueFromString( const wxString& text, int flags = wxPG_PROGRAMMATIC_VALUE );
    bool SetValueFromInt( long value, int flags = 0 );
    virtual wxSize OnMeasureImage( int item = -1 ) const;
    virtual bool OnEvent( wxPropertyGrid* propgrid, wxWindow* wnd_primary, wxEvent& event );
    virtual void ChildChanged( wxVariant& thisValue, int childIndex, wxVariant& childValue ) const;
    void ActualChildChanged( wxVariant& thisValue, int childIndex, wxVariant& childValue ) const {
      ChildChanged( thisValue, childIndex, childValue );
    }

    bool ActualValidateValue( wxVariant& value, wxPGValidationInfo& validationInfo ) const {
      return ValidateValue( value, validationInfo );
    }

    bool ActualStringToValue( wxVariant& variant, const wxString& text, int argFlags = 0 ) const {
      return StringToValue( variant, text, argFlags );
    }

    bool ActualIntToValue( wxVariant& variant, int number, int argFlags = 0 ) const {
      return IntToValue( variant, number, argFlags );
    }

    wxString GetValueType() const {
      return m_value.GetType();
    }
    virtual const wxPGEditor* DoGetEditorClass() const;
    virtual wxValidator* DoGetValidator() const;
    virtual int GetChoiceInfo( wxPGChoiceInfo* choiceinfo );
    virtual void OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& paintdata );
    virtual wxPGCellRenderer* GetCellRenderer( int column ) const;
    virtual void RefreshChildren();
    virtual bool DoSetAttribute( const wxString& name, wxVariant& value );
    virtual wxVariant DoGetAttribute( const wxString& name ) const;
    virtual wxPGEditorDialogAdapter* GetEditorDialog() const;
    virtual void OnValidationFailure( wxVariant& pendingValue );
    int AppendChoice( const wxString& label, int value = wxPG_INVALID_VALUE ) {
      return InsertChoice( label, -1, value );
    }
    wxPGCell* AcquireCell( unsigned int column ) {
      if( column >= m_cells.size() ) {
        return NULL;
      }
      wxPGCell* cell = ( wxPGCell* ) m_cells[column];
      m_cells[column] = NULL;
      return cell;
    }
    bool AreChildrenComponents() const {
      if( m_flags & ( wxPG_PROP_COMPOSED_VALUE | wxPG_PROP_AGGREGATE ) ) {
        return true;
      }
      return false;
    }
    void AddPrivateChild( wxPGProperty* prop ) {
      AddChild( prop );
    }
    wxPGProperty* AppendChild( wxPGProperty* prop ) {
      return InsertChild( -1, prop );
    }
    wxPGProperty* InsertChild( int index, wxPGProperty* childProperty );
    void DeleteChildren();
    void DeleteChoice( int index );
    void Empty() {
      DeleteChildren();
    }
    void EnableCommonValue( bool enable = true ) {
      if( enable ) {
        SetFlag( wxPG_PROP_USES_COMMON_VALUE );
      } else
      { ClearFlag( wxPG_PROP_USES_COMMON_VALUE ); }
    }
    void GenerateComposedValue( wxString& text, int argFlags = 0 ) const;
    const wxString& GetLabel() const { return m_label; }
    wxString GetName() const;
    const wxString& GetBaseName() const { return m_name; }
    wxPGChoices& GetChoices();
    const wxPGChoices& GetChoices() const;
    const wxPGChoiceEntry* GetCurrentChoice() const;
    int GetY() const;

    wxVariant GetValue() const {
      return DoGetValue();
    }
    wxVariant& GetValueRef() {
      return m_value;
    }

    const wxVariant& GetValueRef() const {
      return m_value;
    }
    wxString GetValueString( int argFlags = 0 ) const;
    wxPGCell* GetCell( unsigned int column ) const {
      if( column >= m_cells.size() ) {
        return NULL;
      }
      return ( wxPGCell* ) m_cells[column];
    }
    wxPGCell* GetOrCreateCell( unsigned int column );
    const wxChar* GetClassName() const {
      return GetClassInfo()->GetClassName();
    }
    unsigned int GetChoiceCount() const;
    wxString GetChoiceString( unsigned int index );
    int GetDisplayedCommonValueCount() const;
    wxString GetDisplayedString() const {
      return GetValueString( 0 );
    }
    wxPropertyGrid* GetGrid() const;
    wxPropertyGrid* GetGridIfDisplayed() const;
    wxPGProperty* GetMainParent() const;
    wxPGProperty* GetParent() const { return m_parent; }
    bool IsFlagSet( FlagType flag ) const {
      return ( m_flags & flag ) ? true : false;
    }

    bool IsTextEditable() const;
    bool IsValueUnspecified() const {
      return m_value.IsNull();
    }

    FlagType HasFlag( FlagType flag ) const {
      return ( m_flags & flag );
    }
    bool CanHaveExtraChildren() const {
      return !IsFlagSet( wxPG_PROP_AGGREGATE );
    }
    const wxPGAttributeStorage& GetAttributes() const {
      return m_attributes;
    }
    wxVariant GetAttributesAsList() const;

    FlagType GetFlags() const {
      return m_flags;
    }

    const wxPGEditor* GetEditorClass() const;
    const wxPGEditor* GetColumnEditor( int column ) const {
      if( column == 1 ) {
        return GetEditorClass();
      }
      return NULL;
    }

    int GetCommonValue() const {
      return m_commonValue;
    }
    wxString GetType() const {
      return m_value.GetType();
    }
    bool HasVisibleChildren() const;
    int InsertChoice( const wxString& label, int index, int value = wxPG_INVALID_VALUE );
    bool IsCategory() const { return IsFlagSet( wxPG_PROP_CATEGORY ); }
    bool IsRoot() const { return ( m_parent == NULL ); }
    bool IsSubProperty() const {
      wxPGProperty* parent = ( wxPGProperty* )m_parent;
      if( parent && !parent->IsCategory() ) {
        return true;
      }
      return false;
    }
    const wxPGProperty* GetLastVisibleSubItem() const;

    wxVariant GetDefaultValue() const;

    int GetMaxLength() const {
      return ( int ) m_maxLen;
    }

    bool AreAllChildrenSpecified( wxVariant* pendingList = NULL ) const;
    wxPGProperty* UpdateParentValues();
    FlagType UsesAutoUnspecified() const {
      return HasFlag( wxPG_PROP_AUTO_UNSPECIFIED );
    }

    wxBitmap* GetValueImage() const {
      return m_valueBitmap;
    }
    wxVariant GetAttribute( const wxString& name ) const;
    wxString GetAttribute( const wxString& name, const wxString& defVal ) const;
    long GetAttributeAsLong( const wxString& name, long defVal ) const;
    double GetAttributeAsDouble( const wxString& name, double defVal ) const;
    inline unsigned int GetArrIndex() const { return m_arrIndex; }
    inline unsigned int GetDepth() const { return ( unsigned int )m_depth; }
    wxString GetFlagsAsString( FlagType flagsMask ) const;
    unsigned int GetIndexInParent() const {
      return m_arrIndex;
    }

    bool Hide( bool hide, int flags = wxPG_RECURSE );
    bool IsExpanded() const { return ( !( m_flags & wxPG_PROP_COLLAPSED ) && GetChildCount() ); }
    bool IsVisible() const;
    bool IsEnabled() const {
      return ( m_flags & wxPG_PROP_DISABLED ) ? false : true;
    }
    bool RecreateEditor();
    void RefreshEditor();
    void SetAttribute( const wxString& name, wxVariant value );
    void SetAttributes( const wxPGAttributeStorage& attributes );
    void SetDefaultValue( wxVariant& value ) {
      SetAttribute( _T( "DefaultValue" ), value );
    }
    void SetEditor( const wxPGEditor* editor ) {
      m_customEditor = editor;
    }
    inline void SetEditor( const wxString& editorName );
    void SetCell( int column, wxPGCell* cellObj );
    void SetChoiceSelection( int newValue, const wxPGChoiceInfo& choiceInfo );
    void SetCommonValue( int commonValue ) {
      m_commonValue = commonValue;
    }
    void SetFlagsFromString( const wxString& str );
    void SetValueInEvent( wxVariant value ) const;

    void SetValue( wxVariant value, wxVariant* pList = NULL,
                   int flags = wxPG_SETVAL_REFRESH_EDITOR );
    void SetValueImage( wxBitmap& bmp );
    void SetChoicesExclusive();

    void SetExpanded( bool expanded ) {
      if( !expanded ) {
        m_flags |= wxPG_PROP_COLLAPSED;
      } else {
        m_flags &= ~wxPG_PROP_COLLAPSED;
      }
    }

    void SetFlag( FlagType flag ) { m_flags |= flag; }
    void ChangeFlag( FlagType flag, bool set ) {
      if( set ) {
        m_flags |= flag;
      } else {
        m_flags &= ~flag;
      }
    }

    void SetFlagRecursively( FlagType flag, bool set );
    void SetHelpString( const wxString& helpString ) {
      m_helpString = helpString;
    }
    void SetLabel( const wxString& label ) { m_label = label; }
    void SetName( const wxString& newName );
    void SetValueToUnspecified() {
      wxVariant val;  // Create NULL variant
      SetValue( val, NULL, wxPG_SETVAL_REFRESH_EDITOR );
    }

    void SetValidator( const wxValidator& validator ) {
      m_validator = wxDynamicCast( validator.Clone(), wxValidator );
    }
    wxValidator* GetValidator() const {
      if( m_validator ) {
        return m_validator;
      }
      return DoGetValidator();
    }

    bool PrepareValueForDialogEditing( wxPropertyGrid* propgrid );

    ClientDataType GetClientData() const {
      return m_clientData;
    }

    void SetClientData( ClientDataType clientData ) {
      m_clientData = clientData;
    }

    bool SetChoices( wxPGChoices& choices );
    inline bool SetChoices( const wxArrayString& labels, const wxArrayInt& values = wxPG_EMPTY_ARRAYINT );
    inline bool SetMaxLength( int maxLen );
    void SetWasModified( bool set = true ) {
      if( set ) {
        m_flags |= wxPG_PROP_WAS_MODIFIED;
      } else {
        m_flags &= ~wxPG_PROP_WAS_MODIFIED;
      }
    }

    const wxString& GetHelpString() const {
      return m_helpString;
    }

    void ClearFlag( FlagType flag ) { m_flags &= ~( flag ); }
    bool IsSomeParent( wxPGProperty* candidate_parent ) const;
    void AdaptListToValue( wxVariant& list, wxVariant* value ) const;
    int GetChildrenHeight( int lh, int iMax = -1 ) const;
    unsigned int GetChildCount() const {
      return ( unsigned int ) m_children.GetCount();
    }
    unsigned int GetCount() const {
      return GetChildCount();
    }
    wxPGProperty* Item( unsigned int i ) const {
      return ( wxPGProperty* )m_children.Item( i );
    }
    wxPGProperty* Last() const { return ( wxPGProperty* )m_children.Last(); }
    int Index( const wxPGProperty* p ) const { return m_children.Index( ( wxPGProperty* )p ); }
    void FixIndexesOfChildren( unsigned int starthere = 0 );
    wxPropertyGridState* GetParentState() const { return m_parentState; }
    wxPGProperty* GetItemAtY( unsigned int y, unsigned int lh, unsigned int* nextItemY ) const;
    wxPGProperty* GetPropertyByName( const wxString& name ) const;
    int GetImageOffset( int imageWidth ) const;

  protected:
    void AddChild( wxPGProperty* prop );
    wxString GetColumnText( unsigned int col ) const;
    wxPGProperty* GetPropertyByNameWH( const wxString& name, unsigned int hintIndex ) const;
    void AddChild2( wxPGProperty* prop, int index = -1, bool correct_mode = true );
    bool DoHide( bool hide, int flags );
    void DoSetName( const wxString& str ) { m_name = str; }
    void DoEmpty();
    bool IsChildSelected( const bool recursive = false ) const;
    void PrepareSubProperties();
    void SetParentalType( int flag ) {
      m_flags = ( m_flags & ( ~( wxPG_PROP_PROPERTY | wxPG_PROP_PARENTAL_FLAGS ) ) ) | flag;
    }
    void SetParentState( wxPropertyGridState* pstate ) { m_parentState = pstate; }
    void SubPropsChanged( int oldSelInd = -1 );
    int GetY2( int lh ) const;
    wxString                    m_label;
    wxString                    m_name;
    wxPGProperty*               m_parent;
    wxPropertyGridState*        m_parentState;
    ClientDataType              m_clientData;
    const wxPGEditor*           m_customEditor;
    #if wxUSE_VALIDATORS
    wxValidator*                m_validator;
    #endif

    wxBitmap*                   m_valueBitmap;
    wxVariant                   m_value;
    wxPGAttributeStorage        m_attributes;
    wxArrayPtrVoid              m_children;
    wxArrayPtrVoid              m_cells;
    wxString                    m_helpString;
    unsigned int                m_arrIndex;
    int                         m_commonValue;
    FlagType                    m_flags;
    short                       m_maxLen;
    unsigned char               m_depth;
    unsigned char               m_depthBgCol;
    unsigned char               m_bgColIndex;
    unsigned char               m_fgColIndex;
  private:
    void Init();
    void Init( const wxString& label, const wxString& name );
};

#define wxPGPropNameStr            const wxString&
#define wxPGNameConv(STR)      STR

WX_DECLARE_VOIDPTR_HASH_MAP_WITH_DECL( void*, wxPGHashMapP2P, class WXDLLIMPEXP_PG );
WX_DECLARE_HASH_MAP_WITH_DECL( wxInt32, wxInt32, wxIntegerHash, wxIntegerEqual, wxPGHashMapI2I, class WXDLLIMPEXP_PG );

class WXDLLIMPEXP_PG wxPGRootProperty : public wxPGProperty {
  public:
    WX_PG_DECLARE_PROPERTY_CLASS( wxPGRootProperty )
  public:
    wxPGRootProperty();
    virtual ~wxPGRootProperty();

    virtual bool StringToValue( wxVariant&, const wxString&, int ) const {
      return false;
    }

    virtual void ChildChanged( wxVariant&, int, wxVariant& ) const {
    }

  protected:
};

class WXDLLIMPEXP_PG wxPropertyCategory : public wxPGProperty {
    WX_PG_DECLARE_PROPERTY_CLASS( wxPropertyCategory )
  public:
    wxPropertyCategory();
    wxPropertyCategory( const wxString& label, const wxString& name = wxPG_LABEL );
    ~wxPropertyCategory();
    virtual wxString GetValueAsString( int argFlags ) const;
    virtual void ChildChanged( wxVariant&, int, wxVariant& ) const { }
    int GetTextExtent( const wxWindow* wnd, const wxFont& font ) const;
    void CalculateTextExtent( wxWindow* wnd, const wxFont& font );
    void SetTextColIndex( unsigned int colInd ) { m_capFgColIndex = ( wxByte ) colInd; }
    unsigned int GetTextColIndex() const { return ( unsigned int ) m_capFgColIndex; }
  protected:
    int     m_textExtent;
    wxByte  m_capFgColIndex;
  private:
    void Init();
};

class WXDLLIMPEXP_PG wxPGCommonValue {
  public:
    wxPGCommonValue( const wxString& label, wxPGCellRenderer* renderer ) {
      m_label = label;
      m_renderer = renderer;
      renderer->IncRef();
    }
    virtual ~wxPGCommonValue() {
      m_renderer->DecRef();
    }
    virtual wxString GetEditableText() const { return m_label; }
    const wxString& GetLabel() const { return m_label; }
    wxPGCellRenderer* GetRenderer() const { return m_renderer; }
  protected:
    wxString m_label;
    wxPGCellRenderer* m_renderer;
};

class WXDLLIMPEXP_PG wxPGChoiceEntry : public wxPGCell {
  public:
    wxPGChoiceEntry();
    wxPGChoiceEntry( const wxPGChoiceEntry& entry );
    wxPGChoiceEntry( const wxString& label, int value = wxPG_INVALID_VALUE )
      : wxPGCell(), m_value( value ) {
      m_text = label;
    }

    wxPGChoiceEntry( const wxString& label, int value, const wxBitmap& bitmap,
                     const wxColour& fgCol = wxNullColour, const wxColour& bgCol = wxNullColour )
      : wxPGCell( label, bitmap, fgCol, bgCol ), m_value( value ) {
    }
    virtual ~wxPGChoiceEntry() {
    }
    void SetValue( int value ) { m_value = value; }
    int GetValue() const { return m_value; }
  protected:
    int m_value;
};

typedef void* wxPGChoicesId;

class WXDLLIMPEXP_PG wxPGChoicesData {
    friend class wxPGChoices;
  public:
    wxPGChoicesData();
    void CopyDataFrom( wxPGChoicesData* data );
    void Insert( int index, wxPGChoiceEntry* item ) {
      wxArrayPtrVoid::iterator it;
      if( index == -1 ) {
        it = m_items.end();
        index = ( int ) m_items.size();
      } else
      { it = m_items.begin() + index; }
      if( item->GetValue() == wxPG_INVALID_VALUE ) {
        item->SetValue( index );
      }
      m_items.insert( it, item );
    }
    void Clear();
    unsigned int GetCount() const {
      return ( unsigned int ) m_items.size();
    }
    wxPGChoiceEntry* Item( unsigned int i ) const {
      return ( wxPGChoiceEntry* ) m_items[i];
    }
    void DecRef() {
      m_refCount--;
      wxASSERT( m_refCount >= 0 );
      if( m_refCount == 0 ) {
        delete this;
      }
    }
  private:
    wxArrayPtrVoid  m_items;
    int m_refCount;
    virtual ~wxPGChoicesData();
};

#define wxPGChoicesEmptyData    ((wxPGChoicesData*)NULL)

class WXDLLIMPEXP_PG wxPGChoices {
  public:
    wxPGChoices() {
      Init();
    }
    wxPGChoices( const wxPGChoices& src ) {
      if( src.m_data != wxPGChoicesEmptyData ) {
        m_data = src.m_data;
        m_data->m_refCount++;
      }
    }
    wxPGChoices( const wxChar** labels, const long* values = NULL ) {
      Init();
      Set( labels, values );
    }
    wxPGChoices( const wxArrayString& labels, const wxArrayInt& values = wxPG_EMPTY_ARRAYINT ) {
      Init();
      Set( labels, values );
    }
    wxPGChoices( wxPGChoicesData* data ) {
      wxASSERT( data );
      m_data = data;
      data->m_refCount++;
    }

    ~wxPGChoices() {
      Free();
    }

    void AssignData( wxPGChoicesData* data );
    void Assign( const wxPGChoices& src ) {
      AssignData( src.m_data );
    }
    void operator= ( const wxPGChoices& a ) {
      AssignData( a.m_data );
    }
    typedef long ValArrItem;
    void Add( const wxChar** labels, const ValArrItem* values = NULL );
    void Add( const wxArrayString& arr, const ValArrItem* values = NULL );
    void Add( const wxArrayString& arr, const wxArrayInt& arrint );

    wxPGChoiceEntry& Add( const wxString& label, int value = wxPG_INVALID_VALUE );
    wxPGChoiceEntry& Add( const wxString& label, const wxBitmap& bitmap, int value = wxPG_INVALID_VALUE );
    wxPGChoiceEntry& Add( const wxPGChoiceEntry& entry ) {
      return Insert( entry, -1 );
    }

    wxPGChoiceEntry& AddAsSorted( const wxString& label, int value = wxPG_INVALID_VALUE );

    void Clear() {
      if( m_data != wxPGChoicesEmptyData ) {
        m_data->Clear();
      }
    }

    wxPGChoices Copy() const {
      wxPGChoices dst;
      dst.EnsureData();
      dst.m_data->CopyDataFrom( m_data );
      return dst;
    }

    void EnsureData() {
      if( m_data == wxPGChoicesEmptyData ) {
        m_data = new wxPGChoicesData();
      }
    }

    const wxPGChoiceEntry& Item( unsigned int i ) const {
      wxASSERT( IsOk() );
      return *m_data->Item( i );
    }

    wxPGChoiceEntry& Item( unsigned int i ) {
      wxASSERT( IsOk() );
      return *m_data->Item( i );
    }

    wxPGChoiceEntry& operator[]( unsigned int i ) {
      return Item( i );
    }

    const wxPGChoiceEntry& operator[]( unsigned int i ) const {
      return Item( i );
    }

    bool IsOk() const {
      return ( m_data != wxPGChoicesEmptyData );
    }

    wxPGChoicesId GetId() const { return ( wxPGChoicesId ) m_data; };

    void RemoveAt( size_t nIndex, size_t count = 1 );
    void Set( const wxChar** labels, const long* values = NULL ) {
      Free();
      Add( labels, values );
    }

    void Set( wxArrayString& arr, const long* values = ( const long* ) NULL ) {
      Free();
      Add( arr, values );
    }
    void Set( const wxArrayString& labels, const wxArrayInt& values = wxPG_EMPTY_ARRAYINT ) {
      Free();
      Add( labels, values );
    }
    void SetExclusive() {
      if( m_data->m_refCount != 1 ) {
        wxPGChoicesData* data = new wxPGChoicesData();
        data->CopyDataFrom( m_data );
        Free();
        m_data = data;
      }
    }
    const wxString& GetLabel( unsigned int ind ) const {
      wxASSERT( ind >= 0 && ind < GetCount() );
      return Item( ind ).GetText();
    }
    unsigned int GetCount() const {
      if( m_data ) {
        return m_data->GetCount();
      }
      return 0;
    }
    int GetValue( unsigned int ind ) const { return Item( ind ).GetValue(); }
    wxArrayInt GetValuesForStrings( const wxArrayString& strings ) const;
    wxArrayInt GetIndicesForStrings( const wxArrayString& strings, wxArrayString* unmatched = NULL ) const;
    int Index( const wxString& str ) const;
    int Index( int val ) const;
    wxPGChoiceEntry& Insert( const wxString& label, int index, int value = wxPG_INVALID_VALUE );
    wxPGChoiceEntry& Insert( const wxPGChoiceEntry& entry, int index );
    wxPGChoicesData* GetData() {
      wxASSERT( m_data->m_refCount != 0xFFFFFFF );
      m_data->m_refCount++;
      return m_data;
    }
    wxPGChoicesData* GetDataPtr() const { return m_data; }
    wxPGChoicesData* ExtractData() {
      wxPGChoicesData* data = m_data;
      m_data = wxPGChoicesEmptyData;
      return data;
    }
    wxArrayString GetLabels() const;
  protected:
    wxPGChoicesData* m_data;
    void Init();
    void Free();
};


#if 8 < 7 || ( 8 == 7 && 12 < 1 )

#error mm

WX_DECLARE_OBJARRAY_WITH_DECL( double, wxArrayDouble, class WXDLLIMPEXP_PG );
#endif

#define wxPG_CONSTFUNC(PROP) PROP##Create
#define wxPG_PROPCLASS(PROP) PROP

#define wxPG_NEWPROPERTY(PROP,LABEL,NAME,VALUE) wx##PROP##Property(LABEL,NAME,VALUE)
WXDLLIMPEXP_PG wxObject* wxPG_VariantToWxObject( const wxVariant& variant, wxClassInfo* classInfo );

#undef wxGetVariantCast
#define wxGetVariantCast(var,classname) (classname*)wxPG_VariantToWxObject(var,&classname::ms_classInfo)
#define WX_PG_VARIANT_TO_WXOBJECT(VARIANT,CLASSNAME) (CLASSNAME*)wxPG_VariantToWxObject(VARIANT,&CLASSNAME::ms_classInfo)
#define wxPG_IT_CHILDREN(A)         (A<<16)

enum wxPG_ITERATOR_FLAGS {

  wxPG_ITERATE_PROPERTIES = ( wxPG_PROP_PROPERTY | wxPG_PROP_MISC_PARENT | wxPG_PROP_AGGREGATE | \
                              wxPG_PROP_COLLAPSED | ( ( wxPG_PROP_MISC_PARENT | wxPG_PROP_CATEGORY ) << 16 ) ),
  wxPG_ITERATE_HIDDEN = ( wxPG_PROP_HIDDEN | wxPG_IT_CHILDREN( wxPG_PROP_COLLAPSED ) ),
  wxPG_ITERATE_FIXED_CHILDREN = ( wxPG_IT_CHILDREN( wxPG_PROP_AGGREGATE ) | wxPG_ITERATE_PROPERTIES ),
  wxPG_ITERATE_CATEGORIES = ( wxPG_PROP_CATEGORY | wxPG_IT_CHILDREN( wxPG_PROP_CATEGORY ) | wxPG_PROP_COLLAPSED ),
  wxPG_ITERATE_ALL_PARENTS = ( wxPG_PROP_MISC_PARENT | wxPG_PROP_AGGREGATE | wxPG_PROP_CATEGORY ),
  wxPG_ITERATE_ALL_PARENTS_RECURSIVELY = ( wxPG_ITERATE_ALL_PARENTS | wxPG_IT_CHILDREN( wxPG_ITERATE_ALL_PARENTS ) ),
  wxPG_ITERATOR_FLAGS_ALL = ( wxPG_PROP_PROPERTY | wxPG_PROP_MISC_PARENT | wxPG_PROP_AGGREGATE | \
                              wxPG_PROP_HIDDEN | wxPG_PROP_CATEGORY | wxPG_PROP_COLLAPSED ),

  wxPG_ITERATOR_MASK_OP_ITEM = wxPG_ITERATOR_FLAGS_ALL,
  wxPG_ITERATOR_MASK_OP_PARENT = wxPG_ITERATOR_FLAGS_ALL,
  wxPG_ITERATE_VISIBLE = ( wxPG_ITERATE_PROPERTIES | wxPG_PROP_CATEGORY | wxPG_IT_CHILDREN( wxPG_PROP_AGGREGATE ) ),
  wxPG_ITERATE_ALL = ( wxPG_ITERATE_VISIBLE | wxPG_ITERATE_HIDDEN ),
  wxPG_ITERATE_NORMAL = ( wxPG_ITERATE_PROPERTIES | wxPG_ITERATE_HIDDEN ),
  wxPG_ITERATE_DEFAULT = wxPG_ITERATE_NORMAL

};


#define wxPG_ITERATOR_CREATE_MASKS(FLAGS, A, B) \
  A = (FLAGS ^ wxPG_ITERATOR_MASK_OP_ITEM) & wxPG_ITERATOR_MASK_OP_ITEM & 0xFFFF; \
  B = ((FLAGS>>16) ^ wxPG_ITERATOR_MASK_OP_PARENT) & wxPG_ITERATOR_MASK_OP_PARENT & 0xFFFF;



#define wxPG_ITERATOR_PARENTEXMASK_TEST(PWC, PARENTMASK) \
  ( \
    !(PWC->GetFlags() & PARENTMASK) && \
    PWC->GetChildCount() \
  )


class WXDLLIMPEXP_PG wxPropertyGridIteratorBase {
  public:
    wxPropertyGridIteratorBase() {
    }
    void Assign( const wxPropertyGridIteratorBase& it );
    bool AtEnd() const { return m_property == NULL; }
    wxPGProperty* GetProperty() const { return m_property; }
    void Init( wxPropertyGridState* state, int flags, wxPGProperty* property, int dir = 1 );
    void Init( wxPropertyGridState* state, int flags, int startPos = wxTOP, int dir = 0 );
    void Next( bool iterateChildren = true );
    void Prev();
    void SetBaseParent( wxPGProperty* baseParent ) { m_baseParent = baseParent; }
  protected:
    wxPGProperty* m_property;
  private:
    wxPropertyGridState* m_state;
    wxPGProperty* m_baseParent;
    int m_itemExMask;
    int m_parentExMask;
};


#define wxPG_IMPLEMENT_ITERATOR(CLASS, PROPERTY, STATE) \
  CLASS( STATE* state, int flags = wxPG_ITERATE_DEFAULT, PROPERTY* property = NULL, int dir = 1 ) \
    : wxPropertyGridIteratorBase() \
  { Init( (wxPropertyGridState*)state, flags, (wxPGProperty*)property, dir ); } \
  CLASS( STATE* state, int flags, int startPos, int dir = 0 ) \
    : wxPropertyGridIteratorBase() \
  { Init( (wxPropertyGridState*)state, flags, startPos, dir ); } \
  CLASS() \
    : wxPropertyGridIteratorBase() \
  { \
    m_property = NULL; \
  } \
  CLASS( const CLASS& it ) \
    : wxPropertyGridIteratorBase( ) \
  { \
    Assign(it); \
  } \
  ~CLASS() \
  { \
  } \
  const CLASS& operator=( const CLASS& it ) \
  { \
    Assign(it); \
    return *this; \
  } \
  CLASS& operator++() { Next(); return *this; } \
  CLASS operator++(int) { CLASS it=*this;Next();return it; } \
  CLASS& operator--() { Prev(); return *this; } \
  CLASS operator--(int) { CLASS it=*this;Prev();return it; } \
  PROPERTY* operator *() const { return (PROPERTY*)m_property; } \
  static PROPERTY* OneStep( STATE* state, int flags = wxPG_ITERATE_DEFAULT, PROPERTY* property = NULL, int dir = 1 ) \
  { \
    CLASS it( state, flags, property, dir ); \
    if ( property ) \
    { \
      if ( dir == 1 ) it.Next(); \
      else it.Prev(); \
    } \
    return *it; \
  }

class WXDLLIMPEXP_PG wxPropertyGridIterator : public wxPropertyGridIteratorBase {
  public:
    wxPG_IMPLEMENT_ITERATOR( wxPropertyGridIterator, wxPGProperty, wxPropertyGridState )
  protected:
};

class WXDLLIMPEXP_PG wxPropertyGridConstIterator : public wxPropertyGridIteratorBase {
  public:
    wxPG_IMPLEMENT_ITERATOR( wxPropertyGridConstIterator, const wxPGProperty, const wxPropertyGridState )
    wxPropertyGridConstIterator( const wxPropertyGridIterator& other ) {
      Assign( other );
    }
    const wxPropertyGridConstIterator& operator=( const wxPropertyGridIterator& it ) {
      Assign( it );
      return *this;
    }
  protected:
};

class WXDLLIMPEXP_PG wxPGVIteratorBase {
    friend class wxPGVIterator;
  public:
    wxPGVIteratorBase() { m_refCount = 1; }
    virtual void Next() = 0;
    void IncRef() {
      m_refCount++;
    }
    void DecRef() {
      m_refCount--;
      if( m_refCount <= 0 ) {
        delete this;
      }
    }
  protected:
    virtual ~wxPGVIteratorBase() { }

    wxPropertyGridIterator  m_it;
  private:
    int     m_refCount;
};

class WXDLLIMPEXP_PG wxPGVIterator {
  public:
    wxPGVIterator() { m_pIt = NULL; }
    wxPGVIterator( wxPGVIteratorBase* obj ) { m_pIt = obj; }
    ~wxPGVIterator() { UnRef(); }
    void UnRef() { if( m_pIt ) m_pIt->DecRef(); }
    wxPGVIterator( const wxPGVIterator& it ) {
      m_pIt = it.m_pIt;
      m_pIt->IncRef();
    }
    const wxPGVIterator& operator=( const wxPGVIterator& it ) {
      UnRef();
      m_pIt = it.m_pIt;
      m_pIt->IncRef();
      return *this;
    }
    void Next() { m_pIt->Next(); }
    bool AtEnd() const { return m_pIt->m_it.AtEnd(); }
    wxPGProperty* GetProperty() const { return m_pIt->m_it.GetProperty(); }
  protected:
    wxPGVIteratorBase*  m_pIt;
};

class WXDLLIMPEXP_PG wxPropertyGridHitTestResult {
    friend class wxPropertyGrid;
  public:
    wxPropertyGridHitTestResult() {
      property = NULL;
      column = -1;
      splitter = -1;
      splitterHitOffset = 0;
    }

    ~wxPropertyGridHitTestResult() {
    }

    int GetColumn() const { return column; }
    wxPGProperty* GetProperty() const {
      return property;
    }

    int GetSplitter() const { return splitter; }
    int GetSplitterHitOffset() const { return splitterHitOffset; }
    wxPGProperty*   property;
    int column;
    int splitter;
    int splitterHitOffset;
};

enum wxPG_VALIDATION_FAILURE_BEHAVIOR_FLAGS {
  wxPG_VFB_STAY_IN_PROPERTY = 0x01,
  wxPG_VFB_BEEP = 0x02,
  wxPG_VFB_MARK_CELL = 0x04,
  wxPG_VFB_SHOW_MESSAGE = 0x08,
  wxPG_VFB_SHOW_MESSAGEBOX = 0x10,
  wxPG_VFB_SHOW_MESSAGE_ON_STATUSBAR = 0x20,
  wxPG_VFB_DEFAULT = wxPG_VFB_STAY_IN_PROPERTY | wxPG_VFB_BEEP,
  wxPG_VFB_UNDEFINED = 0x80

};

#define wxPGVFBFlags unsigned char

struct WXDLLIMPEXP_PG wxPGValidationInfo {
  wxVariant*      m_pValue;
  wxString        m_failureMessage;
  wxPGVFBFlags    m_failureBehavior;
  bool            m_isFailing;
  wxPGValidationInfo() {
    m_failureBehavior = 0;
    m_isFailing = false;
  }
  ~wxPGValidationInfo() {
  }
  wxPGVFBFlags GetFailureBehavior() const { return m_failureBehavior; }
  void SetFailureBehavior( wxPGVFBFlags failureBehavior ) { m_failureBehavior = failureBehavior; }
  const wxString& GetFailureMessage() const { return m_failureMessage; }
  void SetFailureMessage( const wxString& message ) { m_failureMessage = message; }
};

enum wxPG_KEYBOARD_ACTIONS {
  wxPG_ACTION_INVALID = 0,
  wxPG_ACTION_NEXT_PROPERTY,
  wxPG_ACTION_PREV_PROPERTY,
  wxPG_ACTION_EXPAND_PROPERTY,
  wxPG_ACTION_COLLAPSE_PROPERTY,
  wxPG_ACTION_CANCEL_EDIT,
  wxPG_ACTION_CUT,
  wxPG_ACTION_COPY,
  wxPG_ACTION_PASTE,
  wxPG_ACTION_SELECT_ALL,
  wxPG_ACTION_EDIT,
  wxPG_ACTION_MAX
};

class WXDLLIMPEXP_PG wxPropertyGridState {
    friend class wxPGProperty;
    friend class wxPropertyGrid;
    friend class wxPGCanvas;
    friend class wxPropertyGridPage;
    friend class wxPropertyGridManager;
    friend class wxPropertyGridInterface;
  public:
    wxPropertyGridState();
    virtual ~wxPropertyGridState();
    wxPGProperty* DoAppend( wxPGProperty* property );
    wxPGProperty* BaseGetPropertyByName( wxPGPropNameStr name ) const;
    void DoClear();
    bool DoIsPropertySelected( wxPGProperty* prop ) const;
    void ClearModifiedStatus( wxPGProperty* p );
    bool DoClearSelection() {
      return DoSelectProperty( NULL );
    }
    void DoRemoveFromSelection( wxPGProperty* prop );
    bool DoCollapse( wxPGProperty* p );
    bool DoExpand( wxPGProperty* p );
    void CalculateFontAndBitmapStuff( int vspacing );
    void CheckColumnWidths( int widthChange = 0 );
    virtual void DoDelete( wxPGProperty* item, bool doDelete = true );
    wxSize DoFitColumns( bool allowGridResize = false );
    wxPGProperty* DoGetItemAtY( int y ) const;
    virtual wxPGProperty* DoInsert( wxPGProperty* parent, int index, wxPGProperty* property );
    virtual void DoSetSplitterPosition( int pos, int splitterColumn = 0, bool allPages = false, bool fromAutoCenter = false );
    bool EnableCategories( bool enable );
    void EnsureVirtualHeight() {
      if( m_vhCalcPending ) {
        RecalculateVirtualHeight();
        m_vhCalcPending = 0;
      }
    }
    bool DoEnableProperty( wxPGProperty* p, bool enable );
    unsigned int GetVirtualHeight() const {
      wxASSERT( !m_vhCalcPending );
      return m_virtualHeight;
    }
    unsigned int GetVirtualHeight() {
      EnsureVirtualHeight();
      return m_virtualHeight;
    }

    inline unsigned int GetActualVirtualHeight() const;

    unsigned int GetColumnCount() const {
      return ( unsigned int ) m_colWidths.size();
    }

    int GetColumnMinWidth( int column ) const;
    int GetColumnWidth( unsigned int column ) const {
      return m_colWidths[column];
    }

    wxPropertyGrid* GetGrid() const { return m_pPropGrid; }
    wxPGProperty* GetLastItem( int flags = wxPG_ITERATE_DEFAULT );

    const wxPGProperty* GetLastItem( int flags = wxPG_ITERATE_DEFAULT ) const {
      return ( ( wxPropertyGridState* )this )->GetLastItem( flags );
    }

    wxPropertyCategory* GetPropertyCategory( const wxPGProperty* p ) const;
    wxPGProperty* GetPropertyByLabel( const wxString& name, wxPGProperty* parent = NULL ) const;
    wxVariant DoGetPropertyValues( const wxString& listname, wxPGProperty* baseparent, long flags ) const;
    wxPGProperty* DoGetRoot() const { return m_properties; }
    int GetVirtualWidth() const {
      return m_width;
    }
    int GetColumnFitWidth( wxClientDC& dc, wxPGProperty* pwc, unsigned int col, bool subProps ) const;

    int GetColumnFullWidth( wxClientDC &dc, wxPGProperty *p, unsigned int col );
    wxPGProperty* GetSelection() const {
      if( m_selection.size() == 0 ) {
        return NULL;
      }
      return m_selection[0];
    }

    void DoSetSelection( wxPGProperty* prop ) {
      m_selection.clear();
      if( prop ) {
        m_selection.push_back( prop );
      }
    }

    void DoSetColumnProportion( unsigned int column, int proportion );
    int DoGetColumnProportion( unsigned int column ) const {
      return m_columnProportions[column];
    }

    void ResetColumnSizes( bool fromAutoCenter );
    wxPropertyGridHitTestResult HitTest( const wxPoint& pt ) const;

    inline bool IsDisplayed() const;

    bool IsInNonCatMode() const { return ( bool )( m_properties == m_abcArray ); }
    void InitNonCatMode();
    void DoLimitPropertyEditing( wxPGProperty* p, bool limit = true ) {
      p->SetFlagRecursively( wxPG_PROP_NOEDITOR, limit );
    }

    bool DoSelectProperty( wxPGProperty* p, unsigned int flags = 0 );
    void OnClientWidthChange( int newWidth, int widthChange, bool fromOnResize = false );
    void RecalculateVirtualHeight() {
      m_virtualHeight = GetActualVirtualHeight();
    }
    void SetColumnCount( int colCount );
    void PropagateColSizeDec( int column, int decrease, int dir );
    bool DoHideProperty( wxPGProperty* p, bool hide, int flags = wxPG_RECURSE );
    bool DoSetPropertyValueString( wxPGProperty* p, const wxString& value );
    bool DoSetPropertyValue( wxPGProperty* p, wxVariant& value );
    bool DoSetPropertyValueWxObjectPtr( wxPGProperty* p, wxObject* value );
    void DoSetPropertyValues( const wxVariantList& list, wxPGProperty* default_category );

#define SetPropertyUnspecified SetPropertyValueUnspecified

    void SetSplitterLeft( bool subProps = false );
    void SetVirtualWidth( int width );
    void Sort( wxPGProperty* p );
    void Sort();
    void VirtualHeightChanged() {
      m_vhCalcPending = 1;
    }

  protected:
    bool ArePropertiesAdjacent( wxPGProperty* prop1, wxPGProperty* prop2, int iterFlags = wxPG_ITERATE_VISIBLE ) const;
    int DoGetSplitterPosition( int splitterIndex = 0 ) const;
    int HitTestH( int x, int* pSplitterHit, int* pSplitterHitOffset ) const;
    int PrepareToAddItem( wxPGProperty* property, wxPGProperty* scheduledParent );
    wxPropertyGrid*             m_pPropGrid;
    wxPGProperty*               m_properties;
    wxPGRootProperty            m_regularArray;
    wxPGRootProperty*           m_abcArray;
    wxPGHashMapS2P              m_dictName;
    wxArrayInt                  m_colWidths;
    wxArrayInt                  m_editableColumns;
    wxArrayInt                  m_columnProportions;
    double                      m_fSplitterX;
    wxPropertyCategory*         m_currentCategory;
    wxArrayPGProperty           m_selection;
    int                         m_width;
    unsigned int                m_virtualHeight;
    unsigned char               m_lastCaptionBottomnest;
    unsigned char               m_itemsAdded;
    unsigned char               m_anyModified;
    unsigned char               m_vhCalcPending;

};

inline bool wxPGProperty::SetChoices( const wxArrayString& labels, const wxArrayInt& values ) {
  wxPGChoices chs( labels, values );
  return SetChoices( chs );
}

#define GetPropertyByNameI          GetPropertyByNameA
#define GetPropertyByNameWithAssert GetPropertyByNameA

#define wxPG_PROP_ARG_CALL_PROLOG_0(PROPERTY) \
  PROPERTY *p = (PROPERTY*)id.GetPtr(this); \
  if ( !p ) return;

#define wxPG_PROP_ARG_CALL_PROLOG_RETVAL_0(PROPERTY, RETVAL) \
  PROPERTY *p = (PROPERTY*)id.GetPtr(this); \
  if ( !p ) return RETVAL;

#define wxPG_PROP_ARG_CALL_PROLOG() \
  wxPG_PROP_ARG_CALL_PROLOG_0(wxPGProperty)

#define wxPG_PROP_ARG_CALL_PROLOG_RETVAL(RVAL) \
  wxPG_PROP_ARG_CALL_PROLOG_RETVAL_0(wxPGProperty, RVAL)

#define wxPG_PROP_ID_CONST_CALL_PROLOG() \
  wxPG_PROP_ARG_CALL_PROLOG_0(const wxPGProperty)

#define wxPG_PROP_ID_CONST_CALL_PROLOG_RETVAL(RVAL) \
  wxPG_PROP_ARG_CALL_PROLOG_RETVAL_0(const wxPGProperty, RVAL)


class WXDLLIMPEXP_PG wxPropertyGridInterface {
    friend class wxPropertyGrid;
    friend class wxPropertyGridManager;
  public:
    virtual ~wxPropertyGridInterface() { };
    void AddPropertyChoice( wxPGPropArg id, const wxString& label, int value = wxPG_INVALID_VALUE );
    wxPGProperty* Append( wxPGProperty* property );
    wxPGProperty* AppendIn( wxPGPropArg id, wxPGProperty* newproperty );
    void BeginAddChildren( wxPGPropArg id );
    void EndAddChildren( wxPGPropArg id );
    void InsertPropertyChoice( wxPGPropArg id, const wxString& label, int index, int value = wxPG_INVALID_VALUE );
    virtual void Clear() = 0;
    bool ClearSelection( bool validation = true );
    bool Collapse( wxPGPropArg id );
    bool CollapseAll() { return ExpandAll( false ); }
    void DeletePropertyChoice( wxPGPropArg id, int index );
    bool ChangePropertyValue( wxPGPropArg id, wxVariant newValue );
    bool ClearPropertyValue( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      p->SetValue( p->GetDefaultValue() );
      return true;
    }

    static wxPGProperty* CreatePropertyByClass( const wxString &classname,
        const wxString &label,
        const wxString &name );

    static wxPGProperty* CreatePropertyByType( const wxString &valuetype,
        const wxString &label,
        const wxString &name );
    void DeleteProperty( wxPGPropArg id );
    wxPGProperty* RemoveProperty( wxPGPropArg id );
    bool DisableProperty( wxPGPropArg id ) { return EnableProperty( id, false ); }
    bool EnableProperty( wxPGPropArg id, bool enable = true );
    bool Expand( wxPGPropArg id );
    bool ExpandAll( bool expand = true );
    wxArrayPGProperty GetExpandedProperties() const {
      wxArrayPGProperty array;
      GetPropertiesWithFlag( &array, wxPG_PROP_COLLAPSED, true, wxPG_ITERATE_ALL_PARENTS_RECURSIVELY | wxPG_ITERATE_HIDDEN );
      return array;
    }

    wxPGProperty* GetFirstChild( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( wxNullProperty )
      if( !p->GetChildCount() || p->IsFlagSet( wxPG_PROP_AGGREGATE ) ) {
        return wxNullProperty;
      }
      return p->Item( 0 );
    }
    wxPropertyGridIterator GetIterator( int flags = wxPG_ITERATE_DEFAULT, wxPGProperty* firstProp = NULL ) {
      return wxPropertyGridIterator( m_pState, flags, firstProp );
    }

    wxPropertyGridConstIterator GetIterator( int flags = wxPG_ITERATE_DEFAULT, wxPGProperty* firstProp = NULL ) const {
      return wxPropertyGridConstIterator( m_pState, flags, firstProp );
    }

    wxPropertyGridIterator GetIterator( int flags, int startPos ) {
      return wxPropertyGridIterator( m_pState, flags, startPos );
    }

    wxPropertyGridConstIterator GetIterator( int flags, int startPos ) const {
      return wxPropertyGridConstIterator( m_pState, flags, startPos );
    }

    virtual wxPGVIterator GetVIterator( int flags ) const;

    wxPGProperty* GetFirst( int flags = wxPG_ITERATE_ALL ) {
      wxPropertyGridIterator it( m_pState, flags, wxNullProperty, 1 );
      return *it;
    }

    const wxPGProperty* GetFirst( int flags = wxPG_ITERATE_ALL ) const {
      return ( ( wxPropertyGridInterface* )this )->GetFirst( flags );
    }
    const wxPGAttributeStorage& GetPropertyAttributes( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( *( ( const wxPGAttributeStorage* )NULL ) );
      return p->GetAttributes();
    }
    void SetPropertyAttributes( wxPGPropArg id, const wxPGAttributeStorage& attributes ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetAttributes( attributes );
    }
    void GetPropertiesWithFlag( wxArrayPGProperty* targetArr, wxPGProperty::FlagType flags, bool inverse = false,
                                int iterFlags = ( wxPG_ITERATE_PROPERTIES | wxPG_ITERATE_HIDDEN | wxPG_ITERATE_CATEGORIES ) ) const;
    wxVariant GetPropertyAttribute( wxPGPropArg id, const wxString& attrName ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( wxNullVariant )
      return p->GetAttribute( attrName );
    }

    wxPGProperty* GetProperty( wxPGPropNameStr name ) const {
      return GetPropertyByName( name );
    }
    wxPGProperty* GetPropertyByName( wxPGPropNameStr name ) const;
    wxPGProperty* GetPropertyByName( wxPGPropNameStr name, wxPGPropNameStr subname ) const;
    wxPGChoices& GetPropertyChoices( wxPGPropArg id );
    wxPG_CONST_WXCHAR_PTR GetPropertyClassName( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( wxPG_CONST_WXCHAR_DEFVAL )
      return p->GetClassName();
    }
    wxPGProperty::ClientDataType GetPropertyClientData( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( NULL )
      return p->GetClientData();
    }
    const wxPGEditor* GetPropertyEditor( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( NULL )
      return p->GetEditorClass();
    }
    wxBitmap* GetPropertyImage( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( NULL )
      return p->GetValueImage();
    }
    unsigned int GetPropertyIndex( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( INT_MAX )
      return p->GetIndexInParent();
    }
    const wxString& GetPropertyLabel( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( m_emptyString )
      return p->GetLabel();
    }
    wxString GetPropertyName( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( m_emptyString )
      return p->GetName();
    }
    wxPGProperty* GetPropertyParent( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( wxNullProperty )
      return p->GetParent();
    }
    wxString GetPropertyHelpString( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( m_emptyString )
      return p->GetHelpString();
    }
    wxString GetPropertyShortClassName( wxPGPropArg id );

    #if wxUSE_VALIDATORS
    wxValidator* GetPropertyValidator( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( NULL )
      return p->GetValidator();
    }
    #endif
    wxVariant GetPropertyValue( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( wxVariant() )
      return p->GetValue();
    }
    wxString GetPropertyValueAsString( wxPGPropArg id ) const;
    long GetPropertyValueAsLong( wxPGPropArg id ) const;
    unsigned long GetPropertyValueAsULong( wxPGPropArg id ) const {
      return ( unsigned long ) GetPropertyValueAsLong( id );
    }
    int GetPropertyValueAsInt( wxPGPropArg id ) const { return ( int )GetPropertyValueAsLong( id ); }
    bool GetPropertyValueAsBool( wxPGPropArg id ) const;
    double GetPropertyValueAsDouble( wxPGPropArg id ) const;
    wxObject* GetPropertyValueAsWxObjectPtr( wxPGPropArg id ) const;
    void* GetPropertyValueAsVoidPtr( wxPGPropArg id ) const;

#define wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL(TYPENAME, DEFVAL) \
  wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFVAL) \
  if ( p->m_value.GetType() != TYPENAME ) \
  { \
    wxPGGetFailed(p,TYPENAME); \
    return DEFVAL; \
  }

#define wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL_WFALLBACK(TYPENAME, DEFVAL) \
  wxPG_PROP_ARG_CALL_PROLOG_RETVAL(DEFVAL) \
  if ( p->m_value.GetType() != TYPENAME ) \
    return DEFVAL; \

    wxArrayString GetPropertyValueAsArrayString( wxPGPropArg id ) const {
      wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL( _T( "arrstring" ), wxArrayString() )
      return p->m_value.GetArrayString();
    }
    wxPoint GetPropertyValueAsPoint( wxPGPropArg id ) const {
      wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL( _T( "wxPoint" ), wxPoint() )
      return WX_PG_VARIANT_GETVALUEREF( p->GetValue(), wxPoint );
    }
    wxSize GetPropertyValueAsSize( wxPGPropArg id ) const {
      wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL( _T( "wxSize" ), wxSize() )
      return WX_PG_VARIANT_GETVALUEREF( p->GetValue(), wxSize );
    }
    wxLongLong_t GetPropertyValueAsLongLong( wxPGPropArg id ) const {
      wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL_WFALLBACK( _T( "wxLongLong" ), ( long ) GetPropertyValueAsLong( id ) )
      return WX_PG_VARIANT_GETVALUEREF( p->GetValue(), wxLongLong ).GetValue();
    }
    wxULongLong_t GetPropertyValueAsULongLong( wxPGPropArg id ) const {
      wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL_WFALLBACK( _T( "wxULongLong" ), ( unsigned long ) GetPropertyValueAsULong( id ) )
      return WX_PG_VARIANT_GETVALUEREF( p->GetValue(), wxULongLong ).GetValue();
    }
    wxArrayInt GetPropertyValueAsArrayInt( wxPGPropArg id ) const {
      wxPG_PROP_ID_GETPROPVAL_CALL_PROLOG_RETVAL( _T( "wxArrayInt" ), wxArrayInt() )
      wxArrayInt arr = WX_PG_VARIANT_GETVALUEREF( p->GetValue(), wxArrayInt );
      return arr;
    }

    #if wxUSE_DATETIME
    wxDateTime GetPropertyValueAsDateTime( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( wxDateTime() )
      if( wxStrcmp( p->m_value.GetType(), _T( "datetime" ) ) != 0 ) {
        wxPGGetFailed( p, _T( "datetime" ) );
        return wxDateTime();
      }
      return p->m_value.GetDateTime();
    }
    #endif

    #if defined(SWIG) || defined(__WXPYTHON__)
    PyObject* GetPropertyValueAsPyObject( wxPGPropArg id ) const;
    #endif

    wxVariant GetPropertyValues( const wxString& listname = wxEmptyString,
                                 wxPGProperty* baseparent = NULL, long flags = 0 ) const {
      return m_pState->DoGetPropertyValues( listname, baseparent, flags );
    }

    wxString GetPropertyValueType( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( m_emptyString )
      return p->GetType();
    }

    wxPGProperty* GetSelection() const;

    const wxArrayPGProperty& GetSelectedProperties() const {
      return m_pState->m_selection;
    }

    wxPropertyGridState* GetState() const { return m_pState; }
    bool HideProperty( wxPGPropArg id, bool hide = true, int flags = wxPG_RECURSE );

    #if wxPG_INCLUDE_ADVPROPS
    static void RegisterAdditionalEditors();
    #else
    static void RegisterAdditionalEditors() { }
    #endif

    #if wxPG_INCLUDE_ADVPROPS
    static void InitAllTypeHandlers();
    #else
    static void InitAllTypeHandlers() { }
    #endif

    wxPGProperty* Insert( wxPGPropArg priorThis, wxPGProperty* newproperty );
    wxPGProperty* Insert( wxPGPropArg parent, int index, wxPGProperty* newproperty );
    bool IsPropertyEnabled( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return ( !( p->GetFlags() & wxPG_PROP_DISABLED ) ) ? true : false;
    }
    virtual bool IsPropertySelected( wxPGPropArg id ) const;
    bool IsPropertyShown( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return ( !( p->GetFlags() & wxPG_PROP_HIDDEN ) ) ? true : false;
    }

    bool IsPropertyExpanded( wxPGPropArg id ) const;

    bool IsPropertyKindOf( wxPGPropArg id, wxClassInfo* info ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return p->IsKindOf( info );
    }
    bool IsPropertyCategory( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return p->IsCategory();
    }
    bool IsPropertyModified( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return ( ( p->GetFlags() & wxPG_PROP_MODIFIED ) ? true : false );
    }

    #ifdef wxPG_COMPATIBILITY_1_0_0
    bool IsPropertyValueUnspecified( wxPGPropArg id ) const
    #else
    bool IsPropertyUnspecified( wxPGPropArg id ) const
    #endif
    {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return p->IsValueUnspecified();
    }

    void LimitPropertyEditing( wxPGPropArg id, bool limit = true );
    void PropertiesToNames( wxArrayString* names, const wxArrayPGProperty& properties ) const;
    void NamesToProperties( wxArrayPGProperty* properties, const wxArrayString& names ) const;
    virtual void RefreshGrid( wxPropertyGridState* state = NULL );
    wxPGProperty* ReplaceProperty( wxPGPropArg id, wxPGProperty* property );
    enum EditableStateFlags {
      SelectionState   = 0x01,
      ExpandedState    = 0x02,
      ScrollPosState   = 0x04,
      PageState        = 0x08,
      SplitterPosState = 0x10,
      DescBoxState     = 0x20,
      AllStates = SelectionState | ExpandedState | ScrollPosState | PageState | SplitterPosState | DescBoxState
    };

    bool RestoreEditableState( const wxString& src, int restoreStates = AllStates );
    wxString SaveEditableState( int includedStates = AllStates ) const;
    static void SetBoolChoices( const wxString& true_choice, const wxString& false_choice );
    bool SetColumnProportion( unsigned int column, int proportion );
    int GetColumnProportion( unsigned int column ) const {
      return m_pState->DoGetColumnProportion( column );
    }
    void SetExpandedProperties( const wxArrayPGProperty& array, bool expand = true ) {
      SetPropertiesFlag( array, wxPG_PROP_COLLAPSED, expand );
    }
    void SetPropertiesFlag( const wxArrayPGProperty& srcArr, wxPGProperty::FlagType flags, bool inverse = false );
    void SetPropertyCell( wxPGPropArg id, int column, const wxString& text = wxEmptyString,
                          const wxBitmap& bitmap = wxNullBitmap, const wxColour& fgCol = wxNullColour,
                          const wxColour& bgCol = wxNullColour ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetCell( column, new wxPGCell( text, bitmap, fgCol, bgCol ) );
    }

    void SetPropertyChoices( wxPGPropArg id, wxPGChoices& choices ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetChoices( choices );
    }
    void SetPropertyChoicesExclusive( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetChoicesExclusive();
    }
    void SetPropertyAttribute( wxPGPropArg id, const wxString& attrName, wxVariant value, long argFlags = 0 ) {
      DoSetPropertyAttribute( id, attrName, value, argFlags );
    }
    void SetPropertyEditor( wxPGPropArg id, const wxPGEditor* editor ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      wxCHECK_RET( editor, _T( "unknown/NULL editor" ) );
      p->SetEditor( editor );
      RefreshProperty( p );
    }
    void SetPropertyEditor( wxPGPropArg id, const wxString& editorName ) {
      SetPropertyEditor( id, GetEditorByName( editorName ) );
    }
    void SetPropertyLabel( wxPGPropArg id, const wxString& newproplabel );
    void SetPropertyClientData( wxPGPropArg id, wxPGProperty::ClientDataType clientData ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetClientData( clientData );
    }
    void SetPropertyValueUnspecified( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetValueToUnspecified();
    }
    void SetPropertyReadOnly( wxPGPropArg id, bool set = true, int flags = wxPG_RECURSE ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      if( flags & wxPG_RECURSE ) {
        p->SetFlagRecursively( wxPG_PROP_READONLY, set );
      } else {
        p->ChangeFlag( wxPG_PROP_READONLY, set );
      }
    }
    void SetPropertyValues( const wxVariantList& list, wxPGPropArg defaultCategory = wxNullProperty ) {
      wxPGProperty *p;
      if( defaultCategory.HasName() ) {
        p = defaultCategory.GetPtr( this );
      } else {
        p = defaultCategory.GetPtr0();
      }
      m_pState->DoSetPropertyValues( list, p );
    }
    void SetPropertyValues( const wxVariant& list, wxPGPropArg defaultCategory = wxNullProperty ) {
      SetPropertyValues( list.GetList(), defaultCategory );
    }
    wxPropertyCategory* GetPropertyCategory( wxPGPropArg id ) const {
      wxPG_PROP_ID_CONST_CALL_PROLOG_RETVAL( NULL )
      return m_pState->GetPropertyCategory( p );
    }
    void SetPropertyHelpString( wxPGPropArg id, const wxString& helpString ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetHelpString( helpString );
    }
    void SetPropertyImage( wxPGPropArg id, wxBitmap& bmp ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetValueImage( bmp );
      RefreshProperty( p );
    }
    bool SetPropertyMaxLength( wxPGPropArg id, int maxLen );

    #if wxUSE_VALIDATORS
    void SetPropertyValidator( wxPGPropArg id, const wxValidator& validator ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      p->SetValidator( validator );
    }
    #endif
    void SetPropertyValueLong( wxPGPropArg id, long value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    void SetPropertyValue( wxPGPropArg id, int value ) {
      wxVariant v( ( long )value );
      SetPropVal( id, v );
    }
    void SetPropertyValueDouble( wxPGPropArg id, double value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    void SetPropertyValueBool( wxPGPropArg id, bool value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    void SetPropertyValue( wxPGPropArg id, const wxChar* value ) {
      SetPropertyValueString( id, wxString( value ) );
    }
    void SetPropertyValueArrstr2( wxPGPropArg id, const wxArrayString& value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    #if wxUSE_DATETIME
    void SetPropertyValueDatetime( wxPGPropArg id, const wxDateTime& value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    #endif
    void SetPropertyValueString( wxPGPropArg id, const wxString& value );
    void SetPropertyValueWxObjectPtr( wxPGPropArg id, wxObject* value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    void SetPropertyValue( wxPGPropArg id, void* value ) {
      wxVariant v( value );
      SetPropVal( id, v );
    }
    void SetPropertyValue( wxPGPropArg id, wxObject& value ) {
      wxVariant v( &value );
      SetPropVal( id, v );
    }
    void SetPropertyValue( wxPGPropArg id, wxVariant value ) {
      SetPropVal( id, value );
    }
    void SetPropertyValuePoint( wxPGPropArg id, const wxPoint& value ) {
      wxVariant v = WXVARIANT( value );
      SetPropVal( id, v );
    }
    void SetPropertyValueSize( wxPGPropArg id, const wxSize& value ) {
      wxVariant v = WXVARIANT( value );
      SetPropVal( id, v );
    }
    void SetPropertyValueLongLong( wxPGPropArg id, wxLongLong_t value ) {
      wxVariant v = WXVARIANT( wxLongLong( value ) );
      SetPropVal( id, v );
    }
    void SetPropertyValueULongLong( wxPGPropArg id, wxULongLong_t value ) {
      wxVariant v = WXVARIANT( wxULongLong( value ) );
      SetPropVal( id, v );
    }
    void SetPropertyValueArrint2( wxPGPropArg id, const wxArrayInt& value ) {
      wxVariant v = WXVARIANT( value );
      SetPropVal( id, v );
    }
    void SetPropVal( wxPGPropArg id, wxVariant& value );
    void SetValidationFailureBehavior( int vfbFlags );
    wxPGProperty * GetPropertyByNameA( wxPGPropNameStr name ) const;
    static wxPGEditor * GetEditorByName( const wxString & editorName );
    virtual void RefreshProperty( wxPGProperty * p ) = 0;
  protected:

    bool DoClearSelection( bool validation, int selFlags = 0 );
    virtual bool SetEditableStateItem( const wxString & name, wxVariant value ) {
      wxUnusedVar( name );
      wxUnusedVar( value );
      return false;
    }
    virtual wxVariant GetEditableStateItem( const wxString& name ) const {
      wxUnusedVar( name );
      return wxNullVariant;
    }
    virtual wxPropertyGridState* GetPageState( int pageIndex ) const {
      if( pageIndex <= 0 ) {
        return m_pState;
      }
      return NULL;
    }
    virtual bool DoSelectPage( int index ) { return true; }
    virtual wxPGProperty* DoGetPropertyByName( wxPGPropNameStr name ) const;
    wxPropertyGridState* m_pState;
    void DoSetPropertyAttribute( wxPGPropArg id, const wxString& name, wxVariant& value, long argFlags );
    wxString m_emptyString;
  private:
    wxPropertyGrid* GetPropertyGrid() {
      if( !m_pState ) {
        return NULL;
      }
      return m_pState->GetGrid();
    }
    const wxPropertyGrid* GetPropertyGrid() const {
      if( !m_pState ) {
        return NULL;
      }
      return ( const wxPropertyGrid* ) m_pState->GetGrid();
    }
};

typedef wxPropertyGridInterface wxPropertyContainerMethods;

#define wxPG_SEL_FOCUS      0x0001
#define wxPG_SEL_FORCE      0x0002
#define wxPG_SEL_NONVISIBLE 0x0004
#define wxPG_SEL_NOVALIDATE 0x0008
#define wxPG_SEL_DELETING   0x0010
#define wxPG_SEL_SETUNSPEC  0x0020
#define wxPG_SEL_DIALOGVAL  0x0040
#define wxPG_SEL_DONT_SEND_EVENT        0x0080
#define wxPG_SEL_NO_REFRESH             0x0100
#define wxPG_FL_INITIALIZED                 0x0001
#define wxPG_FL_ACTIVATION_BY_CLICK         0x0002
#define wxPG_FL_DONT_CENTER_SPLITTER        0x0004
#define wxPG_FL_FOCUSED                     0x0008
#define wxPG_FL_MOUSE_CAPTURED              0x0010
#define wxPG_FL_MOUSE_INSIDE                0x0020
#define wxPG_FL_VALUE_MODIFIED              0x0040
#define wxPG_FL_PRIMARY_FILLS_ENTIRE        0x0080
#define wxPG_FL_CUR_USES_CUSTOM_IMAGE       0x0100
#define wxPG_FL_CELL_OVERRIDES_SEL          0x0200
#define wxPG_FL_SCROLLED                    0x0400
#define wxPG_FL_ADDING_HIDEABLES            0x0800
#define wxPG_FL_NOSTATUSBARHELP             0x1000
#define wxPG_FL_CREATEDSTATE                0x2000
#define wxPG_FL_SCROLLBAR_DETECTED          0x4000
#define wxPG_FL_DESC_REFRESH_REQUIRED       0x8000
#define wxPG_FL_IN_MANAGER                  0x00020000
#define wxPG_FL_GOOD_SIZE_SET               0x00040000
#define wxPG_FL_IGNORE_NEXT_NAVKEY          0x00080000
#define wxPG_FL_IN_SELECT_PROPERTY          0x00100000
#define wxPG_FL_STRING_IN_STATUSBAR         0x00200000
#define wxPG_FL_SPLITTER_PRE_SET            0x00400000
#define wxPG_FL_VALIDATION_FAILED           0x00800000
#define wxPG_FL_CATMODE_AUTO_SORT           0x01000000
#define wxPG_MAN_FL_PAGE_INSERTED           0x02000000
#define wxPG_FL_ABNORMAL_EDITOR             0x04000000
#define wxPG_FL_IN_ONCUSTOMEDITOREVENT      0x08000000
#define wxPG_FL_VALUE_CHANGE_IN_EVENT       0x10000000
#define wxPG_FL_FIXED_WIDTH_EDITOR          0x20000000
#define wxPG_FL_HAS_VIRTUAL_WIDTH           0x40000000
#define wxPG_FL_RECALCULATING_VIRTUAL_SIZE  0x80000000

#include "props.h"

class WXDLLIMPEXP_PG wxPropertyGrid : public wxScrolledWindow, public wxPropertyGridInterface {
    friend class wxPropertyGridState;
    friend class wxPropertyGridInterface;
    friend class wxPropertyGridManager;
    friend class wxPGCanvas;
    DECLARE_DYNAMIC_CLASS( wxPropertyGrid )

  public:
    wxPropertyGrid();
    wxPropertyGrid( wxWindow * parent, wxWindowID id = wxID_ANY, const wxPoint & pos = wxDefaultPosition,
                    const wxSize & size = wxDefaultSize, long style = wxPG_DEFAULT_STYLE,
                    const wxString & name = wxPropertyGridNameStr );
    virtual ~wxPropertyGrid();
    void AddActionTrigger( int action, int keycode, int modifiers = 0 );
    static void AutoGetTranslation( bool enable );
    bool CanClose() {
      return DoEditorValidate();
    }

    void ClearActionTriggers( int action );
    bool EditorValidate() {
      return DoEditorValidate();
    }
    void CenterSplitter( bool enableAutoResizing = false );
    bool ChangePropertyValue( wxPGPropArg id, wxVariant newValue );
    bool Create( wxWindow *parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
                 const wxSize& size = wxDefaultSize, long style = wxPG_DEFAULT_STYLE,
                 const wxString& name = wxPropertyGridNameStr );
    virtual void Clear();
    void ClearModifiedStatus( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      m_pState->ClearModifiedStatus( p );
    }
    void ClearModifiedStatus() {
      m_pState->ClearModifiedStatus( m_pState->m_properties );
      m_pState->m_anyModified = false;
    }
    bool UnfocusEditor();
    bool EnableCategories( bool enable );
    wxPanel* GetPanel() const {
      return m_canvas;
    }
    const wxPGCommonValue* GetCommonValue( unsigned int i ) const {
      return ( wxPGCommonValue* ) m_commonValues[i];
    }
    unsigned int GetCommonValueCount() const {
      return ( unsigned int ) m_commonValues.size();
    }
    wxString GetCommonValueLabel( unsigned int i ) const {
      wxASSERT( GetCommonValue( i ) );
      return GetCommonValue( i )->GetLabel();
    }
    bool EnsureVisible( wxPGPropArg id );
    wxSize FitColumns() {
      wxSize sz = m_pState->DoFitColumns();
      return sz;
    }
    wxFont& GetCaptionFont() { return m_captionFont; }
    const wxFont& GetCaptionFont() const { return m_captionFont; }
    wxColour GetCaptionBackgroundColour() const { return m_colCapBack; }
    wxColour GetCaptionForegroundColour() const { return m_colCapFore; }
    wxColour GetCellBackgroundColour() const { return m_colPropBack; }
    wxColour GetCellDisabledTextColour() const { return m_colDisPropFore; }
    wxColour GetCellTextColour() const { return m_colPropFore; }
    unsigned int GetChildrenCount() {
      return GetChildrenCount( m_pState->m_properties );
    }
    unsigned int GetChildrenCount( wxPGPropArg id ) const {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( 0 )
      return p->GetChildCount();
    }
    unsigned int GetColumnCount() const {
      return ( unsigned int ) m_pState->m_colWidths.size();
    }
    wxColour GetEmptySpaceColour() const { return m_colEmptySpace; }
    int GetFontHeight() const { return m_fontHeight; }
    wxPropertyGrid* GetGrid() { return this; }
    wxSize GetImageSize( wxPGProperty* p = NULL, int item = -1 ) const;
    wxRect GetImageRect( wxPGProperty* p, int item ) const;
    wxPGProperty* GetItemAtY( int y ) const { return DoGetItemAtY( y ); }
    wxPGProperty* GetLastItem( int flags = wxPG_ITERATE_DEFAULT ) {
      return m_pState->GetLastItem( flags );
    }
    const wxPGProperty* GetLastItem( int flags = wxPG_ITERATE_DEFAULT ) const {
      return m_pState->GetLastItem( flags );
    }
    wxColour GetLineColour() const { return m_colLine; }
    wxColour GetMarginColour() const { return m_colMargin; }
    wxColour GetPropertyBackgroundColour( wxPGPropArg id ) const;
    wxColour GetPropertyColour( wxPGPropArg id ) const {
      return GetPropertyBackgroundColour( id );
    }
    wxColour GetPropertyTextColour( wxPGPropArg id ) const;
    wxPGProperty* GetPropertyByLabel( const wxString& name ) const {
      return m_pState->GetPropertyByLabel( name );
    }
    wxPGProperty* GetRoot() const { return m_pState->m_properties; }
    int GetRowHeight() const { return m_lineHeight; }
    int GetMarginWidth() const { return m_marginWidth; }
    wxPGProperty* GetSelectedProperty() const { return GetSelection(); }
    wxColour GetSelectionBackgroundColour() const { return m_colSelBack; }
    wxColour GetSelectionForegroundColour() const { return m_colSelFore; }
    int GetSplitterPosition() const { return m_pState->DoGetSplitterPosition( 0 ); }
    wxTextCtrl* GetEditorTextCtrl() const;
    int GetUnspecifiedCommonValue() const { return m_cvUnspecified; }
    wxPGValidationInfo& GetValidationInfo() {
      return m_validationInfo;
    }
    int GetVerticalSpacing() const { return ( int )m_vspacing; }
    bool HasSelection() const { return ( m_pState->m_selection.size() > 0 ); }
    bool HasVirtualWidth() const { return ( m_iFlags & wxPG_FL_HAS_VIRTUAL_WIDTH ) ? true : false; }
    wxPropertyGridHitTestResult HitTest( const wxPoint& pt ) const;
    bool IsAnyModified() const { return ( m_pState->m_anyModified > 0 ); }
    bool IsFrozen() const { return ( m_frozen > 0 ) ? true : false; }
    void OnTLPChanging( wxWindow* newTLP );
    virtual void RefreshProperty( wxPGProperty* p );
    void RefreshEditor();
    void SetColumnCount( int colCount ) {
      m_pState->SetColumnCount( colCount );
      Refresh();
    }
    void SetSplitterLeft( bool subProps = false ) {
      m_pState->SetSplitterLeft( subProps );
    }
    static wxPGEditor* RegisterEditorClass( wxPGEditor* editor, const wxString& name, bool noDefCheck = false );
    void ResetColours();
    void ResetColumnSizes( bool enableAutoResizing = false );
    void SetButtonShortcut( int keycode, bool ctrlDown = false, bool altDown = false );
    void SetCaptionTextColour( wxPGPropArg id, const wxColour& col );
    void SetCurrentCategory( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      wxPropertyCategory* pc = ( wxPropertyCategory* )p;
      wxASSERT( !pc || pc->IsCategory() );
      m_pState->m_currentCategory = pc;
    }
    void SetPropertyAttributeAll( const wxString& attrName, wxVariant value );
    void SetPropertyBackgroundColour( wxPGPropArg id, const wxColour& col, int flags = wxPG_RECURSE );
    void SetPropertyTextColour( wxPGPropArg id, const wxColour& col, int flags = wxPG_RECURSE );
    void SetPropertyColourToDefault( wxPGPropArg id );
    void SetCaptionBackgroundColour( const wxColour& col );
    void SetCaptionForegroundColour( const wxColour& col );
    void SetCellBackgroundColour( const wxColour& col );
    void SetCellDisabledTextColour( const wxColour& col );
    void SetCellTextColour( const wxColour& col );
    void SetEmptySpaceColour( const wxColour& col );
    void SetLineColour( const wxColour& col );
    void SetMarginColour( const wxColour& col );
    void SetSelectionBackground( const wxColour& col );
    void SetSelectionForeground( const wxColour& col );
    void SetSplitterPosition( int newxpos, bool refresh = true ) {
      DoSetSplitterPosition_T( newxpos, refresh, 0 );
      m_iFlags |= wxPG_FL_SPLITTER_PRE_SET;
    }
    void SetSortFunction( wxPGSortCallback sortFunction ) {
      m_sortFunction = sortFunction;
    }
    wxPGSortCallback GetSortFunction() const {
      return m_sortFunction;
    }
    void SetUnspecifiedValueAppearance( const wxPGCell& cell ) {
      m_unspecifiedAppearance.Assign( cell );
    }
    const wxPGCell& GetUnspecifiedValueAppearance() const {
      return m_unspecifiedAppearance;
    }
    wxString GetUnspecifiedValueText( int argFlags = 0 ) const;
    void SetUnspecifiedCommonValue( int index ) { m_cvUnspecified = index; }
    void SetVirtualWidth( int width );
    bool SelectProperty( wxPGPropArg id, bool focus = false ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return DoSelectProperty( p, focus ? wxPG_SEL_FOCUS : 0 );
    }
    void SetSelection( const wxArrayPGProperty& newSelection ) {
      DoSetSelection( newSelection, wxPG_SEL_DONT_SEND_EVENT );
    }
    bool AddToSelection( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return DoAddToSelection( p, wxPG_SEL_DONT_SEND_EVENT );
    }
    bool RemoveFromSelection( wxPGPropArg id ) {
      wxPG_PROP_ARG_CALL_PROLOG_RETVAL( false )
      return DoRemoveFromSelection( p, wxPG_SEL_DONT_SEND_EVENT );
    }

    void MakeColumnEditable( unsigned int column, bool editable = true );
    void BeginLabelEdit( unsigned int column = 0 ) {
      DoBeginLabelEdit( column, wxPG_SEL_DONT_SEND_EVENT );
    }
    void EndLabelEdit( bool commit = true ) {
      DoEndLabelEdit( commit, wxPG_SEL_DONT_SEND_EVENT );
    }
    wxTextCtrl* GetLabelEditor() const;
    void SwitchState( wxPropertyGridState* pNewState );
    void SetPropertyName( wxPGPropArg id, const wxString& newname ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      DoSetPropertyName( p, newname );
    }

    void SetVerticalSpacing( int vspacing ) {
      m_vspacing = ( unsigned char )vspacing;
      CalculateFontAndBitmapStuff( vspacing );
      if( !m_pState->m_itemsAdded ) {
        Refresh();
      }
    }
    void ShowPropertyError( wxPGPropArg id, const wxString& msg ) {
      wxPG_PROP_ARG_CALL_PROLOG()
      DoShowPropertyError( p, msg );
    }
    void Sort();
    void Sort( wxPGPropArg id );
    virtual void SetWindowStyleFlag( long style );
    void EditorsValueWasModified() { m_iFlags |= wxPG_FL_VALUE_MODIFIED; }
    void EditorsValueWasNotModified() {
      m_iFlags &= ~( wxPG_FL_VALUE_MODIFIED );
    }
    bool IsEditorsValueModified() const { return ( m_iFlags & wxPG_FL_VALUE_MODIFIED ) ? true : false; }
    wxWindow* GenerateEditorButton( const wxPoint& pos, const wxSize& sz );
    void FixPosForTextCtrl( wxWindow* ctrl, unsigned int forColumn = 1, const wxPoint& offset = wxPoint( 0, 0 ) );
    wxWindow* GenerateEditorTextCtrl( const wxPoint& pos, const wxSize& sz, const wxString& value,
                                      wxWindow* secondary, int extraStyle = 0, int maxLen = 0, unsigned int forColumn = 1 );
    wxWindow* GenerateEditorTextCtrlAndButton( const wxPoint& pos, const wxSize& sz, wxWindow** psecondary,
        int limited_editing, wxPGProperty* property );
    wxPoint GetGoodEditorDialogPosition( wxPGProperty* p, const wxSize& sz );
    static wxString& ExpandEscapeSequences( wxString& dst_str, wxString& src_str );
    static wxString& CreateEscapeSequences( wxString& dst_str, wxString& src_str );
    wxRect GetPropertyRect( const wxPGProperty* p1, const wxPGProperty* p2 ) const;
    wxWindow* GetEditorControl() const;
    bool IsEditorFocused() const;
    bool AdjustPosForClipperWindow( wxWindow* topCtrlWnd, int* x, int* y );
    wxWindow* GetPrimaryEditor() const {
      return GetEditorControl();
    }
    wxWindow* GetEditorControlSecondary() const {
      return m_wndEditor2;
    }

    virtual bool CommitChangesFromEditor( wxUint32 flags = 0 );
    bool HasInternalFlag( long flag ) const { return ( m_iFlags & flag ) ? true : false; }
    long GetInternalFlags() const { return m_iFlags; }
    void SetInternalFlag( long flag ) { m_iFlags |= flag; }
    void ClearInternalFlag( long flag ) { m_iFlags &= ~( flag ); }
    virtual void DoShowPropertyError( wxPGProperty* property, const wxString& msg );
    virtual void DoHidePropertyError( wxPGProperty* property );
    virtual wxStatusBar* GetStatusBar();
    static void ArrayStringToString( wxString& dst, const wxArrayString& src, wxChar preDelim, wxChar postDelim, int flags );
    void OnCustomEditorEvent( wxCommandEvent &event );
    bool HandleCustomEditorEvent( wxCommandEvent &event );
    void IncFrozen() { m_frozen++; }
    void DecFrozen() { m_frozen--; }
    void OnComboItemPaint( wxPGCustomComboControl* pCb, int item, wxDC* pDc, wxRect& rect, int flags );
    void SendNavigationKeyEvent( int dir );
    static void DoubleToString( wxString& target, double value, int precision, bool removeZeroes, wxString* precTemplate );
    void ValueChangeInEvent( wxVariant variant ) {
      m_changeInEventValue = variant;
      m_iFlags |= wxPG_FL_VALUE_CHANGE_IN_EVENT;
    }

    bool WasValueChangedInEvent() const {
      return ( m_iFlags & wxPG_FL_VALUE_CHANGE_IN_EVENT ) ? true : false;
    }
    bool IsMainButtonEvent( const wxEvent& event ) {
      return ( event.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED ) && ( m_wndSecId == event.GetId() );
    }
    virtual bool DoPropertyChanged( wxPGProperty* p, unsigned int selFlags = 0 );
    virtual bool PerformValidation( wxPGProperty* p, wxVariant& pendingValue );
    bool OnValidationFailure( wxPGProperty* property, wxVariant& invalidValue );
    void OnValidationFailureReset( wxPGProperty* property ) {
      if( property && property->HasFlag( wxPG_PROP_INVALID_VALUE ) ) {
        DoOnValidationFailureReset( property );
        property->ClearFlag( wxPG_PROP_INVALID_VALUE );
      }
      m_validationInfo.m_failureMessage.clear();
    }
    virtual bool DoOnValidationFailure( wxPGProperty* property, wxVariant& invalidValue );
    virtual void DoOnValidationFailureReset( wxPGProperty* property );
    int GetSpacingY() const { return m_spacingy; }
    void SetupTextCtrlValue( const wxString text ) { m_prevTcValue = text; }
    void DrawItem( wxPGProperty* p ) {
      DrawItems( p, p );
    }
    virtual void DrawItemAndChildren( wxPGProperty* p );
    void DrawItemAndValueRelated( wxPGProperty* p );

  protected:
    virtual wxPropertyGridState* CreateState() const;
  public:
    void SetCurControlBoldFont();
    bool DoSelectProperty( wxPGProperty* p, unsigned int flags = 0 );
    virtual bool Destroy();
    virtual wxSize DoGetBestSize() const;
    virtual void Refresh( bool eraseBackground = true,
                          const wxRect *rect = ( const wxRect * ) NULL );
    virtual bool SetFont( const wxFont& font );
    void SetToolTip( const wxString& tipString );
    virtual void Freeze();
    virtual void SetExtraStyle( long exStyle );
    virtual void Thaw();
    virtual bool Reparent( wxWindowBase *newParent );
  protected:
    wxCursor *m_cursorSizeWE;
    wxWindow *m_wndEditor;
    wxWindow *m_wndEditor2;
    wxPanel *m_canvas;
    wxBitmap *m_doubleBuffer;
    wxArrayPtrVoid *m_windowsToDelete;
    wxLongLong m_timeCreated;
    wxVariant m_changeInEventValue;
    int m_wndSecId;
    int m_spacingy;
    int m_width;
    int m_height;
    int m_ncWidth;
    int m_prevVY;
    int m_gutterWidth;
    int m_lineHeight;
    int m_marginWidth;
    int m_buttonSpacingY;
    int m_subgroup_extramargin;
    int m_iconWidth;
    int m_curcursor;
    wxFont m_captionFont;
    int m_fontHeight;
    int m_pushButKeyCode;
    int m_startingSplitterX;
    int m_draggedSplitter;
    wxPGProperty* m_chgInfo_changedProperty;
    wxPGProperty* m_chgInfo_baseChangedProperty;
    wxVariant m_chgInfo_pendingValue;
    wxVariant m_chgInfo_valueList;
    wxPGValidationInfo m_validationInfo;
    wxPGHashMapI2I m_actionTriggers;
    wxPGCell m_editorAppearance;
    wxPGCell m_unspecifiedAppearance;
    wxArrayPGProperty m_deletedProperties;
    wxArrayPGProperty m_removedProperties;
    unsigned short m_coloursCustomized;
    signed char m_dragOffset;
    unsigned char m_dragStatus;
    unsigned char m_mouseSide;
    unsigned char m_editorFocused;
    unsigned char m_frozen;
    unsigned char m_vspacing;
    unsigned char m_pushButKeyCodeNeedsAlt;
    unsigned char m_pushButKeyCodeNeedsCtrl;
    unsigned char m_keyComboConsumed;
    unsigned char m_inDoPropertyChanged;
    unsigned char m_inCommitChangesFromEditor;
    bool m_inDoSelectProperty;
    bool m_inOnValidationFailure;
    wxPGVFBFlags m_permanentValidationFailureBehavior;
    wxUint32 m_iFlags;
    int m_clearThisMany;
    unsigned int m_colHover;
    wxPGProperty* m_propHover;
    wxWindow* m_labelEditor;
    wxPGProperty* m_labelEditorProperty;
    wxWindow* m_eventObject;
    wxWindow* m_curFocused;
    wxWindow* m_tlpClosed;
    wxLongLong m_tlpClosedTime;
    wxWindow* m_tlp;
    wxPropertyGridEvent* m_processedEvent;
    wxPGSortCallback m_sortFunction;
    int m_propHoverY;
    unsigned int m_selColumn;
    int m_ctrlXAdjust;
    wxColour m_colLine;
    wxColour m_colPropFore;
    wxColour m_colDisPropFore;
    wxColour m_colPropBack;
    wxColour m_colCapFore;
    wxColour m_colCapBack;
    wxColour m_colSelFore;
    wxColour m_colSelBack;
    wxColour m_colMargin;
    wxColour m_colEmptySpace;
    wxArrayPtrVoid m_visPropArray;
    wxArrayPtrVoid m_arrBgBrushes;
    wxArrayPtrVoid m_arrFgCols;
    wxArrayPtrVoid m_commonValues;
    int m_cvUnspecified;
    wxString m_prevTcValue;
  protected:
    void Init1();
    void Init2();
    void OnMouseMove( wxMouseEvent &event );
    void OnMouseMoveBottom( wxMouseEvent &event );
    void OnMouseClick( wxMouseEvent &event );
    void OnMouseRightClick( wxMouseEvent &event );
    void OnMouseDoubleClick( wxMouseEvent &event );
    void OnMouseUp( wxMouseEvent &event );
    void OnKey( wxKeyEvent &event );
    void OnKeyUp( wxKeyEvent &event );
    void OnNavigationKey( wxNavigationKeyEvent& event );
    void OnResize( wxSizeEvent &event );
    void OnPaint( wxPaintEvent& event );
    bool HandleMouseMove( int x, unsigned int y, wxMouseEvent &event );
    bool HandleMouseClick( int x, unsigned int y, wxMouseEvent &event );
    bool HandleMouseRightClick( int x, unsigned int y, wxMouseEvent &event );
    bool HandleMouseDoubleClick( int x, unsigned int y, wxMouseEvent &event );
    bool HandleMouseUp( int x, unsigned int y, wxMouseEvent &event );
    void HandleKeyEvent( wxKeyEvent &event );
    bool HandleChildKey( wxKeyEvent& event );
    void OnMouseEntry( wxMouseEvent &event );
    void OnIdle( wxIdleEvent &event );
    void OnFocusEvent( wxFocusEvent &event );
    void OnChildFocusEvent( wxChildFocusEvent& event );
    bool OnMouseCommon( wxMouseEvent &event, int* px, int *py );
    bool OnMouseChildCommon( wxMouseEvent &event, int* px, int *py );
    void OnMouseClickChild( wxMouseEvent &event );
    void OnMouseRightClickChild( wxMouseEvent &event );
    void OnMouseMoveChild( wxMouseEvent &event );
    void OnMouseUpChild( wxMouseEvent &event );
    void OnChildKeyDown( wxKeyEvent &event );
    void OnChildKeyUp( wxKeyEvent &event );
    void OnCaptureChange( wxMouseCaptureChangedEvent &event );
    void OnScrollEvent( wxScrollWinEvent &event );
    void OnSysColourChanged( wxSysColourChangedEvent &event );
    void OnTLPClose( wxCloseEvent& event );
  protected:
    bool AddToSelectionFromInputEvent( wxPGProperty* prop, unsigned int colIndex, wxMouseEvent* event = NULL, int selFlags = 0 );
    void CalculateFontAndBitmapStuff( int vspacing );
    wxRect GetEditorWidgetRect( wxPGProperty* p, int column ) const;
    void CorrectEditorWidgetSizeX();
    void CorrectEditorWidgetPosY();
    #ifdef __WXDEBUG__
    void _log_items();
    void OnScreenNote( const wxChar* format, ... );
    #endif
    int DoDrawItems( wxDC& dc, const wxPGProperty* first_item, const wxPGProperty* last_item, const wxRect* clip_rect,
                     bool isBuffered ) const;
    virtual void DrawExpanderButton( wxDC& dc, const wxRect& rect, wxPGProperty* property ) const;
    void DrawItems( wxDC& dc, unsigned int topitemy, unsigned int bottomitemy,
                    const wxRect* clip_rect = ( const wxRect* ) NULL );
    void DrawItems( const wxPGProperty* p1, const wxPGProperty* p2 );
    int KeyEventToActions( wxKeyEvent &event, int* pSecond ) const;
    int KeyEventToAction( wxKeyEvent &event ) const {
      return KeyEventToActions( event, NULL );
    }
    void ImprovedClientToScreen( int* px, int* py );
    void HandleFocusChange( wxWindow* newFocused );
    void RegainColours();
    bool DoEditorValidate();
    bool DoSelectAndEdit( wxPGProperty* prop, unsigned int colIndex, unsigned int selFlags );
    void DoSetSelection( const wxArrayPGProperty& newSelection, int selFlags = 0 );
    bool DoAddToSelection( wxPGProperty* prop, int selFlags = 0 );
    bool DoRemoveFromSelection( wxPGProperty* prop, int selFlags = 0 );
    void DoBeginLabelEdit( unsigned int colIndex, int selFlags = 0 );
    void DoEndLabelEdit( bool commit, int selFlags = 0 );
    void OnLabelEditorEnterPress( wxCommandEvent& event );
    void OnLabelEditorKeyPress( wxKeyEvent& event );
    wxPGProperty* DoGetItemAtY( int y ) const;
    void DoSetSplitterPosition_T( int newxpos, bool refresh = true, int splitterIndex = 0, bool allPages = false );
    void DestroyEditorWnd( wxWindow* wnd );
    void FreeEditors();
    virtual bool DoExpand( wxPGProperty* p, bool sendEvent );
    virtual bool DoCollapse( wxPGProperty* p, bool sendEvent );
    wxPGProperty* GetNearestPaintVisible( wxPGProperty* p ) const;
    static void RegisterDefaultEditors();
    void SetBackgroundColourIndex( wxPGProperty* p, int index, int flags = wxPG_RECURSE );
    void SetTextColourIndex( wxPGProperty* p, int index, int flags );
    int CacheColour( const wxColour& colour );
    void DoSetPropertyName( wxPGProperty* p, const wxString& newname );
    void SetupEventHandling( wxWindow* wnd, int id );
    void CustomSetCursor( int type, bool override = false );
    virtual bool ProcessEvent( wxEvent& event );
    void RecalculateVirtualSize( int forceXPos = -1 );
    void SetEditorAppearance( const wxPGCell& cell );
    void ResetEditorAppearance() {
      wxPGCell cell;
      SetEditorAppearance( cell );
    }
    void PrepareAfterItemsAdded();
    bool SendEvent( int eventType, wxPGProperty* p, wxVariant* pValue = NULL, unsigned int selFlags = wxPG_SEL_NOVALIDATE,
                    unsigned int column = 1 );
    void SetFocusOnCanvas() {
      m_canvas->SetFocusIgnoringChildren();
      m_editorFocused = 0;
    }
    bool DoHideProperty( wxPGProperty* p, bool hide, int flags );
  private:
    bool ButtonTriggerKeyTest( wxKeyEvent &event );
  private:
    DECLARE_EVENT_TABLE()
};

#undef wxPG_USE_STATE

inline bool wxPropertyGridState::IsDisplayed() const {
  return ( this == m_pPropGrid->GetState() );
}

inline unsigned int wxPropertyGridState::GetActualVirtualHeight() const {
  return DoGetRoot()->GetChildrenHeight( GetGrid()->GetRowHeight() );
}

inline int wxPGProperty::GetDisplayedCommonValueCount() const {
  if( HasFlag( wxPG_PROP_USES_COMMON_VALUE ) ) {
    wxPropertyGrid* pg = GetGrid();
    if( pg ) {
      return ( int ) pg->GetCommonValueCount();
    }
  }
  return 0;
}

inline void wxPGProperty::SetEditor( const wxString& editorName ) {
  m_customEditor = wxPropertyGridInterface::GetEditorByName( editorName );
}

inline bool wxPGProperty::SetMaxLength( int maxLen ) {
  return GetGrid()->SetPropertyMaxLength( this, maxLen );
}

extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_SELECTED;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_CHANGING;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_CHANGED;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_HIGHLIGHTED;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_RIGHT_CLICK;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_PAGE_CHANGED;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_ITEM_EXPANDED;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_ITEM_COLLAPSED;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_DOUBLE_CLICK;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_LABEL_EDIT_BEGIN;
extern WXDLLIMPEXP_PG const wxEventType wxEVT_PG_LABEL_EDIT_ENDING;

#define wxPG_BASE_EVT_TYPE       wxEVT_PG_SELECTED
#define wxPG_MAX_EVT_TYPE        (wxPG_BASE_EVT_TYPE+30)

typedef void ( wxEvtHandler::*wxPropertyGridEventFunction )( wxPropertyGridEvent& );

#define EVT_PG_SELECTED(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_SELECTED, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_CHANGING(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_CHANGING, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_CHANGED(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_CHANGED, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_HIGHLIGHTED(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_HIGHLIGHTED, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_RIGHT_CLICK(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_RIGHT_CLICK, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_DOUBLE_CLICK(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_DOUBLE_CLICK, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_PAGE_CHANGED(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_PAGE_CHANGED, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_ITEM_COLLAPSED(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_ITEM_COLLAPSED, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_ITEM_EXPANDED(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_ITEM_EXPANDED, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_LABEL_EDIT_BEGIN(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_LABEL_EDIT_BEGIN, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),
#define EVT_PG_LABEL_EDIT_ENDING(id, fn)   DECLARE_EVENT_TABLE_ENTRY( wxEVT_PG_LABEL_EDIT_ENDING, id, -1,   \
    (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxPropertyGridEventFunction, & fn ), (wxObject *) NULL ),

#define wxPropertyGridEventHandler(A) ((wxObjectEventFunction)(wxEventFunction)(wxPropertyGridEventFunction)&A)

class WXDLLIMPEXP_PG wxPropertyGridEvent : public wxCommandEvent {
  public:
    wxPropertyGridEvent( wxEventType commandType = 0, int id = 0 );
    wxPropertyGridEvent( const wxPropertyGridEvent& event );
    ~wxPropertyGridEvent();
    virtual wxEvent* Clone() const;
    void EnableProperty( bool enable = true ) {
      m_pg->EnableProperty( m_property, enable );
    }
    void DisableProperty() {
      m_pg->EnableProperty( m_property, false );
    }
    unsigned int GetColumn() const {
      return m_column;
    }

    wxPGProperty* GetMainParent() const {
      wxASSERT( m_property );
      return m_property->GetMainParent();
    }
    wxPGProperty* GetProperty() const {
      return m_property;
    }
    const wxString& GetPropertyLabel() const {
      wxASSERT( m_property );
      return m_property->GetLabel();
    }
    wxString GetPropertyName() const {
      wxASSERT( m_property );
      return m_property->GetName();
    }
    wxPGProperty::ClientDataType GetPropertyClientData() const {
      wxASSERT( m_property );
      return m_property->GetClientData();
    }
    wxVariant GetPropertyValue() const {
      wxASSERT( m_property );
      return m_property->GetValue();
    }

    wxString GetPropertyValueAsString() const {
      return m_pg->GetPropertyValueAsString( m_property );
    }
    long GetPropertyValueAsLong() const {
      return m_pg->GetPropertyValueAsLong( m_property );
    }
    int GetPropertyValueAsInt() const {
      return ( int )GetPropertyValueAsLong();
    }
    long GetPropertyValueAsBool() const {
      return m_pg->GetPropertyValueAsBool( m_property );
    }
    double GetPropertyValueAsDouble() const {
      return m_pg->GetPropertyValueAsDouble( m_property );
    }
    const wxObject* GetPropertyValueAsWxObjectPtr() const {
      return m_pg->GetPropertyValueAsWxObjectPtr( m_property );
    }
    void* GetPropertyValueAsVoidPtr() const {
      return m_pg->GetPropertyValueAsVoidPtr( m_property );
    }
    wxArrayString GetPropertyValueAsArrayString() const {
      return m_pg->GetPropertyValueAsArrayString( m_property );
    }
    wxPoint GetPropertyValueAsPoint() const {
      return m_pg->GetPropertyValueAsPoint( m_property );
    }
    wxSize GetPropertyValueAsSize() const {
      return m_pg->GetPropertyValueAsSize( m_property );
    }
    wxArrayInt GetPropertyValueAsArrayInt() const {
      return m_pg->GetPropertyValueAsArrayInt( m_property );
    }
    wxPGValidationInfo & GetValidationInfo() {
      wxASSERT( m_validationInfo );
      return *m_validationInfo;
    }
    bool HasProperty() const { return ( m_property != ( wxPGProperty* ) NULL ); }
    bool IsPropertyEnabled() const {
      return m_pg->IsPropertyEnabled( m_property );
    }
    bool CanVeto() const { return m_canVeto; }
    void Veto( bool veto = true ) { m_wasVetoed = veto; }
    const wxVariant& GetValue() const {
      wxASSERT_MSG( m_validationInfo, _T( "仅从支持它的事件类型处理程序调用GetValue" ) );
      return *m_validationInfo->m_pValue;
    }
    void SetValidationFailureBehavior( int flags ) {
      wxASSERT( GetEventType() == wxEVT_PG_CHANGING );
      m_validationInfo->m_failureBehavior = ( wxPGVFBFlags ) flags;
    }
    void SetValidationFailureMessage( const wxString& message ) {
      wxASSERT( GetEventType() == wxEVT_PG_CHANGING );
      m_validationInfo->m_failureMessage = message;
    }
    wxPGVFBFlags GetValidationFailureBehavior() const {
      wxASSERT( GetEventType() == wxEVT_PG_CHANGING );
      return m_validationInfo->m_failureBehavior;
    }

    void SetCanVeto( bool canVeto ) { m_canVeto = canVeto; }
    bool WasVetoed() const { return m_wasVetoed; }
    void SetProperty( wxPGProperty* p ) { m_property = p; }
    void SetPropertyGrid( wxPropertyGrid* pg ) { m_pg = pg; }
    void SetupValidationInfo() {
      wxASSERT( m_pg );
      wxASSERT( GetEventType() == wxEVT_PG_CHANGING );
      m_validationInfo = &m_pg->GetValidationInfo();
    }
    void SetColumn( unsigned int column ) {
      m_column = column;
    }

  private:
    void Init();
    DECLARE_DYNAMIC_CLASS( wxPropertyGridEvent )
    wxPGProperty* m_property;
    wxPropertyGrid* m_pg;
    wxPGValidationInfo* m_validationInfo;
    unsigned int m_column;
    bool m_canVeto;
    bool m_wasVetoed;

};

class WXDLLIMPEXP_PG wxPropertyGridPopulator {
  public:
    wxPropertyGridPopulator();
    virtual ~wxPropertyGridPopulator();
    void SetState( wxPropertyGridState* state );
    void SetGrid( wxPropertyGrid* pg );
    wxPGProperty* Add( const wxString& propClass, const wxString& propLabel, const wxString& propName,
                       const wxString* propValue, wxPGChoices* pChoices = NULL );
    void AddChildren( wxPGProperty* property );
    bool AddAttribute( const wxString& name, const wxString& type, const wxString& value );
    virtual void DoScanForChildren() = 0;
    wxPGProperty* GetCurParent() const {
      return ( wxPGProperty* ) m_propHierarchy[m_propHierarchy.size() - 1];
    }
    wxPropertyGridState* GetState() { return m_state; }
    const wxPropertyGridState* GetState() const { return m_state; }
    static bool ToLongPCT( const wxString& s, long* pval, long max );
    wxPGChoices ParseChoices( const wxString& choicesString, const wxString& idString );
    virtual void ProcessError( const wxString& msg );
  protected:
    wxPropertyGrid*         m_pg;
    wxPropertyGridState*    m_state;
    wxArrayPGProperty       m_propHierarchy;
    wxPGHashMapS2P          m_dictIdChoices;
};


#ifndef __wxPG_SOURCE_FILE__
#undef wxPG_FL_DESC_REFRESH_REQUIRED
#undef wxPG_FL_SCROLLBAR_DETECTED
#undef wxPG_FL_CREATEDSTATE
#undef wxPG_FL_NOSTATUSBARHELP
#undef wxPG_FL_SCROLLED
#undef wxPG_FL_FOCUS_INSIDE_CHILD
#undef wxPG_FL_FOCUS_INSIDE
#undef wxPG_FL_MOUSE_INSIDE_CHILD
#undef wxPG_FL_CUR_USES_CUSTOM_IMAGE
#undef wxPG_FL_PRIMARY_FILLS_ENTIRE
#undef wxPG_FL_VALUE_MODIFIED
#undef wxPG_FL_MOUSE_INSIDE
#undef wxPG_FL_FOCUSED
#undef wxPG_FL_MOUSE_CAPTURED
#undef wxPG_FL_INITIALIZED
#undef wxPG_FL_ACTIVATION_BY_CLICK
#undef wxPG_FL_DONT_CENTER_SPLITTER
#undef wxPG_SUPPORT_TOOLTIPS
#undef wxPG_DOUBLE_BUFFER
#undef wxPG_ICON_WIDTH
#undef wxPG_USE_RENDERER_NATIVE
#endif

#endif
